forked from upstream-mirrors/OpenTracks
Code compiles now. Removed large parts of sync.
This commit is contained in:
-90
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the {@link SendMapsActivity}.
|
|
||||||
*
|
|
||||||
* @author Youtao Liu
|
|
||||||
*/
|
|
||||||
public class SendMapsActivityTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
private SendMapsActivity sendMapsActivity;
|
|
||||||
private SendRequest sendRequest;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
sendRequest = new SendRequest(1L);
|
|
||||||
sendMapsActivity = new SendMapsActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
|
||||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and false.
|
|
||||||
*/
|
|
||||||
public void testGetNextClass_notCancelSendFusionTables() {
|
|
||||||
sendRequest.setSendFusionTables(true);
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
|
||||||
assertEquals(SendFusionTablesActivity.class, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
|
||||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to false, true and false.
|
|
||||||
*/
|
|
||||||
public void testGetNextClass_notCancelSendSpreadsheets() {
|
|
||||||
sendRequest.setSendFusionTables(false);
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
|
||||||
assertEquals(SendSpreadsheetsActivity.class, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
|
||||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to false, false and false.
|
|
||||||
*/
|
|
||||||
public void testGetNextClass_notCancelNotSend() {
|
|
||||||
sendRequest.setSendFusionTables(false);
|
|
||||||
sendRequest.setSendSpreadsheets(false);
|
|
||||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
|
||||||
assertEquals(UploadResultActivity.class, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
|
||||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and true.
|
|
||||||
*/
|
|
||||||
public void testGetNextClass_cancelSendSpreadsheets() {
|
|
||||||
sendRequest.setSendFusionTables(true);
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, true);
|
|
||||||
assertEquals(UploadResultActivity.class, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-327
@@ -1,327 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
|
||||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.testing.mocking.AndroidMock;
|
|
||||||
import com.google.android.testing.mocking.UsesMocks;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendMapsAsyncTask}.
|
|
||||||
*
|
|
||||||
* @author Youtao Liu
|
|
||||||
*/
|
|
||||||
public class SendMapsAsyncTaskTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
private static final long TRACK_ID = 1;
|
|
||||||
// Records the run times of {@link SendMapsAsyncTaskMock#uploadMarker(String,
|
|
||||||
// String, String, Location)}
|
|
||||||
private int uploadMarkerCounter = 0;
|
|
||||||
// Records the run times of {@link
|
|
||||||
// SendMapsAsyncTaskMock#prepareAndUploadPoints(Track, List<Location>,
|
|
||||||
// boolean)}
|
|
||||||
private int prepareAndUploadPointsCounter = 0;
|
|
||||||
|
|
||||||
private SendMapsActivity sendMapsActivityMock;
|
|
||||||
private MyTracksProviderUtils myTracksProviderUtilsMock;
|
|
||||||
private SendRequest sendRequest;
|
|
||||||
|
|
||||||
private class SendMapsAsyncTaskMock extends SendMapsAsyncTask {
|
|
||||||
|
|
||||||
private boolean[] uploadMarkerResult = { false, false };
|
|
||||||
private boolean prepareAndUploadPointsResult = false;
|
|
||||||
|
|
||||||
private SendMapsAsyncTaskMock(SendMapsActivity activity, long trackId, Account account,
|
|
||||||
MyTracksProviderUtils myTracksProviderUtils) {
|
|
||||||
super(activity, trackId, account, myTracksProviderUtils);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean uploadMarker(String title, String description, String iconUrl, Location location) {
|
|
||||||
int runTimes = uploadMarkerCounter++;
|
|
||||||
return uploadMarkerResult[runTimes];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean prepareAndUploadPoints(Track track, List<Location> locations, boolean lastBatch) {
|
|
||||||
prepareAndUploadPointsCounter++;
|
|
||||||
return prepareAndUploadPointsResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@UsesMocks({ SendMapsActivity.class, MyTracksProviderUtils.class })
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
uploadMarkerCounter = 0;
|
|
||||||
prepareAndUploadPointsCounter = 0;
|
|
||||||
sendMapsActivityMock = AndroidMock.createMock(SendMapsActivity.class);
|
|
||||||
myTracksProviderUtilsMock = AndroidMock.createMock(MyTracksProviderUtils.class);
|
|
||||||
sendRequest = new SendRequest(TRACK_ID);
|
|
||||||
AndroidMock.expect(sendMapsActivityMock.getApplicationContext()).andReturn(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendMapsAsyncTask#fetchSendMapId(Track)} when chooseMapId is
|
|
||||||
* null and makes sure it returns false.
|
|
||||||
*/
|
|
||||||
public void testFetchSendMapId_nullMapID() {
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
|
|
||||||
// Makes chooseMapId to null.
|
|
||||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
// Returns false for an exception would be thrown.
|
|
||||||
assertFalse(sendMapsAsyncTask.fetchSendMapId(track));
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
|
||||||
* the location iterator has no item. And makes sure it returns true.
|
|
||||||
*/
|
|
||||||
public void testUploadAllTrackPoints_empptyLocationIterator() {
|
|
||||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
|
||||||
locationIterator.close();
|
|
||||||
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
|
||||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
|
||||||
.andReturn(locationIterator);
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
|
||||||
* uploads the first marker is failed.
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadAllTrackPoints_uploadFirstMarkerFailed() {
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
|
|
||||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true);
|
|
||||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1"));
|
|
||||||
locationIterator.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
|
||||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
|
||||||
.andReturn(locationIterator);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[0] = false;
|
|
||||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
|
||||||
assertEquals(1, uploadMarkerCounter);
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
|
||||||
* uploads the two markers is successful but failed when
|
|
||||||
* prepareAndUploadPoints.
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadAllTrackPoints_prepareAndUploadPointsFailed() {
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
|
|
||||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
|
||||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
|
||||||
locationIterator.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
|
||||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
|
||||||
.andReturn(locationIterator);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
// For will be failed when run prepareAndUploadPoints, it no require to
|
|
||||||
// set uploadMarkerResult[1].
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
|
||||||
sendMapsAsyncTask.prepareAndUploadPointsResult = false;
|
|
||||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
|
||||||
assertEquals(1, uploadMarkerCounter);
|
|
||||||
assertEquals(1, prepareAndUploadPointsCounter);
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
|
||||||
* uploads the last marker is failed.
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadAllTrackPoints_uploadLastMarkerFailed() {
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
|
|
||||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
|
||||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
|
||||||
locationIterator.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
|
||||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
|
||||||
.andReturn(locationIterator);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[1] = false;
|
|
||||||
sendMapsAsyncTask.prepareAndUploadPointsResult = true;
|
|
||||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
|
||||||
assertEquals(2, uploadMarkerCounter);
|
|
||||||
assertEquals(1, prepareAndUploadPointsCounter);
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
|
||||||
* return true.a
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadAllTrackPoints_success() {
|
|
||||||
Track track = TrackStubUtils.createTrack(1);
|
|
||||||
|
|
||||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
|
||||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
|
||||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
|
||||||
locationIterator.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
|
||||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
|
||||||
.andReturn(locationIterator);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
|
||||||
sendMapsAsyncTask.uploadMarkerResult[1] = true;
|
|
||||||
sendMapsAsyncTask.prepareAndUploadPointsResult = true;
|
|
||||||
assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
|
||||||
assertEquals(2, uploadMarkerCounter);
|
|
||||||
assertEquals(1, prepareAndUploadPointsCounter);
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when cursor is
|
|
||||||
* null.
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadWaypoints_nullCursor() {
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
|
||||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(null);
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
|
|
||||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
assertTrue(sendMapsAsyncTask.uploadWaypoints());
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when there is
|
|
||||||
* only one point.
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadWaypoints_onePoint() {
|
|
||||||
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
|
|
||||||
AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true);
|
|
||||||
// Only one point, so next is null.
|
|
||||||
AndroidMock.expect(cursorMock.moveToNext()).andReturn(false);
|
|
||||||
cursorMock.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
|
||||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
|
||||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
|
|
||||||
assertTrue(sendMapsAsyncTask.uploadWaypoints());
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()}. Makes sure a
|
|
||||||
* cursor is created and a way point is created with such cursor.
|
|
||||||
*
|
|
||||||
* @throws XmlPullParserException
|
|
||||||
*/
|
|
||||||
@UsesMocks(Cursor.class)
|
|
||||||
public void testUploadWaypoints() throws XmlPullParserException {
|
|
||||||
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
|
|
||||||
MapsGDataConverter mapsGDataConverterMock = new MapsGDataConverter();
|
|
||||||
|
|
||||||
AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true);
|
|
||||||
AndroidMock.expect(cursorMock.moveToNext()).andReturn(true);
|
|
||||||
cursorMock.close();
|
|
||||||
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
|
||||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
|
|
||||||
Waypoint waypoint = new Waypoint();
|
|
||||||
waypoint.setLocation(TrackStubUtils.createMyTracksLocation());
|
|
||||||
AndroidMock.expect(myTracksProviderUtilsMock.createWaypoint(cursorMock))
|
|
||||||
.andReturn(waypoint).times(1);
|
|
||||||
|
|
||||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
|
||||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
|
||||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
|
||||||
sendMapsAsyncTask.setMapsGDataConverter(mapsGDataConverterMock);
|
|
||||||
// Would be failed for there is no source for uploading.
|
|
||||||
assertFalse(sendMapsAsyncTask.uploadWaypoints());
|
|
||||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendMapsAsyncTask#getPercentage(int, int)}.
|
|
||||||
*/
|
|
||||||
public void testCountPercentage() {
|
|
||||||
assertEquals(SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN, SendMapsAsyncTask.getPercentage(0, 5));
|
|
||||||
assertEquals(
|
|
||||||
SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX, SendMapsAsyncTask.getPercentage(50, 50));
|
|
||||||
assertEquals((int) ((double) 5 / 11
|
|
||||||
* (SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX - SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN)
|
|
||||||
+ SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN), SendMapsAsyncTask.getPercentage(5, 11));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-149
@@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendMapsUtils}.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendMapsUtilsTest extends TestCase {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
|
||||||
* Location)} with a title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsMarkerFeature_with_title() {
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(123.0);
|
|
||||||
location.setLongitude(456.0);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
|
||||||
"name", "this\nmap\ndescription", "url", location);
|
|
||||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("name", mapFeature.getTitle());
|
|
||||||
assertEquals("this<br>map<br>description", mapFeature.getDescription());
|
|
||||||
assertEquals("url", mapFeature.getIconUrl());
|
|
||||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
|
||||||
* Location)} with an empty title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsMarkerFeature_empty_title() {
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(123.0);
|
|
||||||
location.setLongitude(456.0);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
|
||||||
"", "description", "url", location);
|
|
||||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("-", mapFeature.getTitle());
|
|
||||||
assertEquals("description", mapFeature.getDescription());
|
|
||||||
assertEquals("url", mapFeature.getIconUrl());
|
|
||||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
|
||||||
* Location)} with a null title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsMarkerFeature_null_title() {
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(123.0);
|
|
||||||
location.setLongitude(456.0);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
|
||||||
null, "description", "url", location);
|
|
||||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("-", mapFeature.getTitle());
|
|
||||||
assertEquals("description", mapFeature.getDescription());
|
|
||||||
assertEquals("url", mapFeature.getIconUrl());
|
|
||||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
|
|
||||||
* title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsLineFeature_with_title() {
|
|
||||||
ArrayList<Location> locations = new ArrayList<Location>();
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(50.0);
|
|
||||||
location.setLongitude(100.0);
|
|
||||||
locations.add(location);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("name", locations);
|
|
||||||
|
|
||||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("name", mapFeature.getTitle());
|
|
||||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
|
||||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with an
|
|
||||||
* empty title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsLineFeature_empty_title() {
|
|
||||||
ArrayList<Location> locations = new ArrayList<Location>();
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(50.0);
|
|
||||||
location.setLongitude(100.0);
|
|
||||||
locations.add(location);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("", locations);
|
|
||||||
|
|
||||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("-", mapFeature.getTitle());
|
|
||||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
|
||||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
|
|
||||||
* null title.
|
|
||||||
*/
|
|
||||||
public void testBuildMapsLineFeature_null_title() {
|
|
||||||
ArrayList<Location> locations = new ArrayList<Location>();
|
|
||||||
Location location = new Location("test");
|
|
||||||
location.setLatitude(50.0);
|
|
||||||
location.setLongitude(100.0);
|
|
||||||
locations.add(location);
|
|
||||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature(null, locations);
|
|
||||||
|
|
||||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
|
||||||
assertNotNull(mapFeature.getAndroidId());
|
|
||||||
assertEquals("-", mapFeature.getTitle());
|
|
||||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
|
||||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
|
||||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-287
@@ -1,287 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the {@link SendRequest}.
|
|
||||||
*
|
|
||||||
* @author Youtao Liu
|
|
||||||
*/
|
|
||||||
public class SendRequestTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
private SendRequest sendRequest;
|
|
||||||
|
|
||||||
private final static String ACCOUNTNAME = "testAccount1";
|
|
||||||
private final static String ACCOUNTYPE = "testType1";
|
|
||||||
private final static String DRIVE_SHARE_EMAILS = "foo@foo.com";
|
|
||||||
private final static String SHARE_URL = "url@url.com";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
sendRequest = new SendRequest(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#getTrackId()}. The value should be set
|
|
||||||
* to 1 when it is initialed in setup method.
|
|
||||||
*/
|
|
||||||
public void testGetTrackId() {
|
|
||||||
assertEquals(1, sendRequest.getTrackId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsSendMaps() {
|
|
||||||
assertEquals(false, sendRequest.isSendMaps());
|
|
||||||
sendRequest.setSendMaps(true);
|
|
||||||
assertEquals(true, sendRequest.isSendMaps());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsSendFusionTables() {
|
|
||||||
assertEquals(false, sendRequest.isSendFusionTables());
|
|
||||||
sendRequest.setSendFusionTables(true);
|
|
||||||
assertEquals(true, sendRequest.isSendFusionTables());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#isSendSpreadsheets()}. The value should
|
|
||||||
* be set to false which is its default value when it is initialed in setup
|
|
||||||
* method.
|
|
||||||
*/
|
|
||||||
public void testIsSendSpreadsheets() {
|
|
||||||
assertEquals(false, sendRequest.isSendSpreadsheets());
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
assertEquals(true, sendRequest.isSendSpreadsheets());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#getAccount()}. The value should be set
|
|
||||||
* to null which is its default value when it is initialed in setup method.
|
|
||||||
*/
|
|
||||||
public void testGetAccount() {
|
|
||||||
assertEquals(null, sendRequest.getAccount());
|
|
||||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
|
||||||
sendRequest.setAccount(account);
|
|
||||||
assertEquals(account, sendRequest.getAccount());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#isMapsSuccess()}. The value should be
|
|
||||||
* set to false which is its default value when it is initialed in setup
|
|
||||||
* method.
|
|
||||||
*/
|
|
||||||
public void testIsMapsSuccess() {
|
|
||||||
assertEquals(false, sendRequest.isMapsSuccess());
|
|
||||||
sendRequest.setMapsSuccess(true);
|
|
||||||
assertEquals(true, sendRequest.isMapsSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#isFusionTablesSuccess()}. The value
|
|
||||||
* should be set to false which is its default value when it is initialed in
|
|
||||||
* setup method.
|
|
||||||
*/
|
|
||||||
public void testIsFusionTablesSuccess() {
|
|
||||||
assertEquals(false, sendRequest.isFusionTablesSuccess());
|
|
||||||
sendRequest.setFusionTablesSuccess(true);
|
|
||||||
assertEquals(true, sendRequest.isFusionTablesSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method {@link SendRequest#isSpreadsheetsSuccess()}. The value
|
|
||||||
* should be set to false which is its default value when it is initialed in
|
|
||||||
* setup method.
|
|
||||||
*/
|
|
||||||
public void testIsSpreadsheetsSuccess() {
|
|
||||||
assertEquals(false, sendRequest.isSpreadsheetsSuccess());
|
|
||||||
sendRequest.setSpreadsheetsSuccess(true);
|
|
||||||
assertEquals(true, sendRequest.isSpreadsheetsSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests SendRequest.CREATOR.createFromParcel when all values are true.
|
|
||||||
*/
|
|
||||||
public void testCreateFromParcel_true() {
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
parcel.writeLong(2);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeString(DRIVE_SHARE_EMAILS);
|
|
||||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
|
||||||
parcel.writeParcelable(account, 0);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeByte((byte) 1);
|
|
||||||
parcel.writeString(SHARE_URL);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
|
|
||||||
assertEquals(2, sendRequest.getTrackId());
|
|
||||||
assertTrue(sendRequest.isSendDrive());
|
|
||||||
assertTrue(sendRequest.isSendMaps());
|
|
||||||
assertTrue(sendRequest.isSendFusionTables());
|
|
||||||
assertTrue(sendRequest.isSendSpreadsheets());
|
|
||||||
assertTrue(sendRequest.isDriveSync());
|
|
||||||
assertTrue(sendRequest.isDriveSharePublic());
|
|
||||||
assertEquals(DRIVE_SHARE_EMAILS, sendRequest.getDriveShareEmails());
|
|
||||||
assertEquals(account, sendRequest.getAccount());
|
|
||||||
assertTrue(sendRequest.isDriveSuccess());
|
|
||||||
assertTrue(sendRequest.isMapsSuccess());
|
|
||||||
assertTrue(sendRequest.isFusionTablesSuccess());
|
|
||||||
assertTrue(sendRequest.isSpreadsheetsSuccess());
|
|
||||||
assertEquals(SHARE_URL, sendRequest.getShareUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests SendRequest.CREATOR.createFromParcel when all values are false.
|
|
||||||
*/
|
|
||||||
public void testCreateFromParcel_false() {
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
parcel.writeLong(4);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeString(null);
|
|
||||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
|
||||||
parcel.writeParcelable(account, 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeByte((byte) 0);
|
|
||||||
parcel.writeString(null);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
|
|
||||||
assertEquals(4, sendRequest.getTrackId());
|
|
||||||
assertFalse(sendRequest.isSendDrive());
|
|
||||||
assertFalse(sendRequest.isSendMaps());
|
|
||||||
assertFalse(sendRequest.isSendFusionTables());
|
|
||||||
assertFalse(sendRequest.isSendSpreadsheets());
|
|
||||||
assertFalse(sendRequest.isDriveSync());
|
|
||||||
assertFalse(sendRequest.isDriveSharePublic());
|
|
||||||
assertNull(sendRequest.getDriveShareEmails());
|
|
||||||
assertEquals(account, sendRequest.getAccount());
|
|
||||||
assertFalse(sendRequest.isDriveSuccess());
|
|
||||||
assertFalse(sendRequest.isMapsSuccess());
|
|
||||||
assertFalse(sendRequest.isFusionTablesSuccess());
|
|
||||||
assertFalse(sendRequest.isSpreadsheetsSuccess());
|
|
||||||
assertNull(sendRequest.getShareUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendRequest#writeToParcel(Parcel, int)} with default values.
|
|
||||||
*/
|
|
||||||
public void testWriteToParcel_default() {
|
|
||||||
sendRequest = new SendRequest(1);
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
sendRequest.writeToParcel(parcel, 1);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
long trackId = parcel.readLong();
|
|
||||||
boolean sendDrive = parcel.readByte() == 1;
|
|
||||||
boolean sendMaps = parcel.readByte() == 1;
|
|
||||||
boolean sendFusionTables = parcel.readByte() == 1;
|
|
||||||
boolean sendSpreadsheets = parcel.readByte() == 1;
|
|
||||||
boolean driveSync = parcel.readByte() == 1;
|
|
||||||
boolean driveSharePublic = parcel.readByte() == 1;
|
|
||||||
String dirveShareEmails = parcel.readString();
|
|
||||||
Parcelable account = parcel.readParcelable(null);
|
|
||||||
boolean driveSuccess = parcel.readByte() == 1;
|
|
||||||
boolean mapsSuccess = parcel.readByte() == 1;
|
|
||||||
boolean fusionTablesSuccess = parcel.readByte() == 1;
|
|
||||||
boolean spreadsheetsSuccess = parcel.readByte() == 1;
|
|
||||||
String shareUrl = parcel.readString();
|
|
||||||
assertEquals(1, trackId);
|
|
||||||
assertFalse(sendDrive);
|
|
||||||
assertFalse(sendMaps);
|
|
||||||
assertFalse(sendFusionTables);
|
|
||||||
assertFalse(sendSpreadsheets);
|
|
||||||
assertFalse(driveSync);
|
|
||||||
assertFalse(driveSharePublic);
|
|
||||||
assertNull(dirveShareEmails);
|
|
||||||
assertNull(account);
|
|
||||||
assertFalse(driveSuccess);
|
|
||||||
assertFalse(mapsSuccess);
|
|
||||||
assertFalse(fusionTablesSuccess);
|
|
||||||
assertFalse(spreadsheetsSuccess);
|
|
||||||
assertNull(shareUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendRequest#writeToParcel(Parcel, int)}.
|
|
||||||
*/
|
|
||||||
public void testWriteToParcel() {
|
|
||||||
sendRequest = new SendRequest(4);
|
|
||||||
sendRequest.setSendDrive(true);
|
|
||||||
sendRequest.setSendMaps(true);
|
|
||||||
sendRequest.setSendFusionTables(true);
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
sendRequest.setDriveSync(true);
|
|
||||||
sendRequest.setDriveSharePublic(true);
|
|
||||||
sendRequest.setDriveShareEmails(DRIVE_SHARE_EMAILS);
|
|
||||||
Account accountNew = new Account(ACCOUNTNAME + "2", ACCOUNTYPE + "2");
|
|
||||||
sendRequest.setAccount(accountNew);
|
|
||||||
sendRequest.setMapsSuccess(true);
|
|
||||||
sendRequest.setDriveSuccess(true);
|
|
||||||
sendRequest.setFusionTablesSuccess(true);
|
|
||||||
sendRequest.setSpreadsheetsSuccess(true);
|
|
||||||
sendRequest.setShareUrl(SHARE_URL);
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
sendRequest.writeToParcel(parcel, 1);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
long trackId = parcel.readLong();
|
|
||||||
boolean sendDrive = parcel.readByte() == 1;
|
|
||||||
boolean sendMaps = parcel.readByte() == 1;
|
|
||||||
boolean sendFusionTables = parcel.readByte() == 1;
|
|
||||||
boolean sendSpreadsheets = parcel.readByte() == 1;
|
|
||||||
boolean driveSync = parcel.readByte() == 1;
|
|
||||||
boolean driveSharePublic = parcel.readByte() == 1;
|
|
||||||
String driveShareEmails = parcel.readString();
|
|
||||||
Parcelable account = parcel.readParcelable(null);
|
|
||||||
boolean driveSuccess = parcel.readByte() == 1;
|
|
||||||
boolean mapsSuccess = parcel.readByte() == 1;
|
|
||||||
boolean fusionTablesSuccess = parcel.readByte() == 1;
|
|
||||||
boolean spreadsheetsSuccess = parcel.readByte() == 1;
|
|
||||||
String shareUrl = parcel.readString();
|
|
||||||
assertEquals(4, trackId);
|
|
||||||
assertTrue(sendDrive);
|
|
||||||
assertTrue(sendMaps);
|
|
||||||
assertTrue(sendFusionTables);
|
|
||||||
assertTrue(sendSpreadsheets);
|
|
||||||
assertTrue(driveSync);
|
|
||||||
assertTrue(driveSharePublic);
|
|
||||||
assertEquals(DRIVE_SHARE_EMAILS, driveShareEmails);
|
|
||||||
assertEquals(accountNew, account);
|
|
||||||
assertTrue(driveSuccess);
|
|
||||||
assertTrue(mapsSuccess);
|
|
||||||
assertTrue(fusionTablesSuccess);
|
|
||||||
assertTrue(spreadsheetsSuccess);
|
|
||||||
assertEquals(SHARE_URL, shareUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-124
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the {@link SendToGoogleUtils}.
|
|
||||||
*
|
|
||||||
* @author Youtao Liu
|
|
||||||
*/
|
|
||||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
public class SendToGoogleUtilsTest extends TestCase {
|
|
||||||
|
|
||||||
private final static long TRACK_ID = 1L;
|
|
||||||
private final static String TRACK_CATEGORY = "trackCategory";
|
|
||||||
private final static String TRACK_NAME = "trackName";
|
|
||||||
private final static double DIFFERENCE = 0.02;
|
|
||||||
private final static double INVALID_LATITUDE = 91;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)}
|
|
||||||
* when there is only one location in a segment.
|
|
||||||
*/
|
|
||||||
public void testPrepareTrackSegment_onlyOneLocation() {
|
|
||||||
Track segment = TrackStubUtils.createTrack(1);
|
|
||||||
assertFalse(SendToGoogleUtils.endSegment(segment, -1L, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)} when there
|
|
||||||
* is no stop time.
|
|
||||||
*/
|
|
||||||
public void testPrepareTrackSegment_noStopTime() {
|
|
||||||
Track segment = TrackStubUtils.createTrack(2);
|
|
||||||
assertEquals(-1L, segment.getTripStatistics().getStopTime());
|
|
||||||
|
|
||||||
ArrayList<Track> tracksArray = new ArrayList<Track>();
|
|
||||||
assertTrue(SendToGoogleUtils.endSegment(
|
|
||||||
segment, segment.getLocations().get(1).getTime(), tracksArray));
|
|
||||||
assertEquals(segment, tracksArray.get(0));
|
|
||||||
// The stop time should be the time of last location
|
|
||||||
assertEquals(
|
|
||||||
segment.getLocations().get(1).getTime(), segment.getTripStatistics().getStopTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the method
|
|
||||||
* {@link SendToGoogleUtils#prepareLocations(Track, java.util.List)} .
|
|
||||||
*/
|
|
||||||
public void testPrepareLocations() {
|
|
||||||
Track trackStub = TrackStubUtils.createTrack(2);
|
|
||||||
trackStub.setId(TRACK_ID);
|
|
||||||
trackStub.setName(TRACK_NAME);
|
|
||||||
trackStub.setCategory(TRACK_CATEGORY);
|
|
||||||
|
|
||||||
List<Location> locationsArray = new ArrayList<Location>();
|
|
||||||
// Adds 100 location to List.
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
// Use this variable as a flag to make all points in the track can be kept
|
|
||||||
// after run the LocationUtils#decimate(Track, double) with
|
|
||||||
// Ramer–Douglas–Peucker algorithm.
|
|
||||||
double latitude = TrackStubUtils.INITIAL_LATITUDE;
|
|
||||||
if (i % 2 == 0) {
|
|
||||||
latitude -= DIFFERENCE * (i % 10);
|
|
||||||
}
|
|
||||||
// Inserts 9 points which have wrong latitude, so would have 10 segments.
|
|
||||||
if (i % 10 == 0 && i > 0) {
|
|
||||||
MyTracksLocation location = TrackStubUtils.createMyTracksLocation();
|
|
||||||
location.setLatitude(INVALID_LATITUDE);
|
|
||||||
locationsArray.add(location);
|
|
||||||
} else {
|
|
||||||
locationsArray.add(TrackStubUtils.createMyTracksLocation(latitude,
|
|
||||||
TrackStubUtils.INITIAL_LONGITUDE + DIFFERENCE * (i % 10),
|
|
||||||
TrackStubUtils.INITIAL_ALTITUDE + DIFFERENCE * (i % 10)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<Track> result = SendToGoogleUtils.prepareLocations(trackStub, locationsArray);
|
|
||||||
assertEquals(10, result.size());
|
|
||||||
// Checks all segments.
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
Track segmentOne = result.get(i);
|
|
||||||
assertEquals(TRACK_ID, segmentOne.getId());
|
|
||||||
assertEquals(TRACK_NAME, segmentOne.getName());
|
|
||||||
assertEquals(TRACK_CATEGORY, segmentOne.getCategory());
|
|
||||||
}
|
|
||||||
// Checks all locations in the first segment.
|
|
||||||
for (int j = 0; j < 9; j++) {
|
|
||||||
double latitude = TrackStubUtils.INITIAL_LATITUDE;
|
|
||||||
if (j % 2 == 0) {
|
|
||||||
latitude -= DIFFERENCE * (j % 10);
|
|
||||||
}
|
|
||||||
Location oneLocation = result.get(0).getLocations().get(j);
|
|
||||||
assertEquals(TrackStubUtils.createMyTracksLocation().getAltitude() + DIFFERENCE * (j % 10),
|
|
||||||
oneLocation.getAltitude());
|
|
||||||
assertEquals(latitude, oneLocation.getLatitude());
|
|
||||||
assertEquals(TrackStubUtils.createMyTracksLocation().getLongitude() + DIFFERENCE * (j % 10),
|
|
||||||
oneLocation.getLongitude());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.spreadsheets;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsUtils;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils}.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendSpreadsheetsUtilsTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with metric units.
|
|
||||||
*/
|
|
||||||
public void testGetDistance_metric() {
|
|
||||||
assertEquals("1.22", SendSpreadsheetsUtils.getDistance(1222.3, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with imperial
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
public void testGetDistance_imperial() {
|
|
||||||
assertEquals("0.76", SendSpreadsheetsUtils.getDistance(1222.3, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with metric units.
|
|
||||||
*/
|
|
||||||
public void testGetSpeed_metric() {
|
|
||||||
assertEquals("15.55", SendSpreadsheetsUtils.getSpeed(4.32, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with imperial units.
|
|
||||||
*/
|
|
||||||
public void testGetSpeed_imperial() {
|
|
||||||
assertEquals("9.66", SendSpreadsheetsUtils.getSpeed(4.32, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with metric
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
public void testGetElevation_metric() {
|
|
||||||
assertEquals("3", SendSpreadsheetsUtils.getElevation(3.456, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with imperial
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
public void testGetElevation_imperial() {
|
|
||||||
assertEquals("11", SendSpreadsheetsUtils.getElevation(3.456, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-243
@@ -22,16 +22,8 @@ import com.google.android.apps.mytracks.fragments.ExportDialogFragment.ExportTyp
|
|||||||
import com.google.android.apps.mytracks.fragments.InstallEarthDialogFragment;
|
import com.google.android.apps.mytracks.fragments.InstallEarthDialogFragment;
|
||||||
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment;
|
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment;
|
||||||
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment.ShareTrackCaller;
|
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment.ShareTrackCaller;
|
||||||
import com.google.android.apps.mytracks.io.drive.SendDriveActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||||
import com.google.android.apps.mytracks.io.file.exporter.SaveActivity;
|
import com.google.android.apps.mytracks.io.file.exporter.SaveActivity;
|
||||||
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants;
|
|
||||||
import com.google.android.apps.mytracks.io.maps.SendMapsActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||||
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
||||||
@@ -72,7 +64,7 @@ import java.io.IOException;
|
|||||||
* @author Jimmy Shih
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity
|
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity
|
||||||
implements CheckPermissionCaller, ShareTrackCaller, ConfirmDeleteCaller {
|
implements ShareTrackCaller, ConfirmDeleteCaller {
|
||||||
|
|
||||||
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
|
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
|
||||||
private static final String SEND_REQUEST_KEY = "send_request_key";
|
private static final String SEND_REQUEST_KEY = "send_request_key";
|
||||||
@@ -83,14 +75,13 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
|
|||||||
protected static final int GOOGLE_PLAY_SERVICES_REQUEST_CODE = 4;
|
protected static final int GOOGLE_PLAY_SERVICES_REQUEST_CODE = 4;
|
||||||
protected static final int CAMERA_REQUEST_CODE = 5;
|
protected static final int CAMERA_REQUEST_CODE = 5;
|
||||||
|
|
||||||
private SendRequest sendRequest;
|
|
||||||
private CheckPermissionAsyncTask asyncTask;
|
private CheckPermissionAsyncTask asyncTask;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
sendRequest = savedInstanceState.getParcelable(SEND_REQUEST_KEY);
|
//sendRequest = savedInstanceState.getParcelable(SEND_REQUEST_KEY);
|
||||||
}
|
}
|
||||||
Object retained = getLastCustomNonConfigurationInstance();
|
Object retained = getLastCustomNonConfigurationInstance();
|
||||||
if (retained instanceof CheckPermissionAsyncTask) {
|
if (retained instanceof CheckPermissionAsyncTask) {
|
||||||
@@ -107,39 +98,9 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
|
|||||||
return asyncTask;
|
return asyncTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
outState.putParcelable(SEND_REQUEST_KEY, sendRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case DRIVE_REQUEST_CODE:
|
|
||||||
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FUSION_TABLES_REQUEST_CODE:
|
|
||||||
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.FUSION_TABLES_NOTIFICATION_ID);
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
onFusionTablesSuccess();
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPREADSHEETS_REQUEST_CODE:
|
|
||||||
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.SPREADSHEETS_NOTIFICATION_ID);
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
onSpreadsheetsPermissionSuccess();
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DELETE_REQUEST_CODE:
|
case DELETE_REQUEST_CODE:
|
||||||
onDeleted();
|
onDeleted();
|
||||||
break;
|
break;
|
||||||
@@ -159,208 +120,6 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
|
|||||||
.show(getSupportFragmentManager(), ShareTrackDialogFragment.SHARE_TRACK_DIALOG_TAG);
|
.show(getSupportFragmentManager(), ShareTrackDialogFragment.SHARE_TRACK_DIALOG_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
|
||||||
sendRequest = new SendRequest(trackId);
|
|
||||||
sendRequest.setSendDrive(true);
|
|
||||||
sendRequest.setDriveSharePublic(makePublic);
|
|
||||||
sendRequest.setDriveShareEmails(emails);
|
|
||||||
sendRequest.setAccount(account);
|
|
||||||
checkPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportTrackToGoogle(long trackId, ExportType exportType, Account account) {
|
|
||||||
sendRequest = new SendRequest(trackId);
|
|
||||||
String pageView;
|
|
||||||
switch (exportType) {
|
|
||||||
case GOOGLE_DRIVE:
|
|
||||||
pageView = AnalyticsUtils.ACTION_EXPORT_DRIVE;
|
|
||||||
sendRequest.setSendDrive(true);
|
|
||||||
break;
|
|
||||||
case GOOGLE_MAPS:
|
|
||||||
pageView = AnalyticsUtils.ACTION_EXPORT_MAPS;
|
|
||||||
sendRequest.setSendMaps(true);
|
|
||||||
break;
|
|
||||||
case GOOGLE_FUSION_TABLES:
|
|
||||||
pageView = AnalyticsUtils.ACTION_EXPORT_FUSION_TABLES;
|
|
||||||
sendRequest.setSendFusionTables(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pageView = AnalyticsUtils.ACTION_EXPORT_SPREADSHEETS;
|
|
||||||
sendRequest.setSendSpreadsheets(true);
|
|
||||||
}
|
|
||||||
AnalyticsUtils.sendPageViews(this, pageView);
|
|
||||||
sendRequest.setAccount(account);
|
|
||||||
checkPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables Google Drive sync.
|
|
||||||
*/
|
|
||||||
protected void enableSync(Account account) {
|
|
||||||
sendRequest = new SendRequest(-1L);
|
|
||||||
sendRequest.setSendDrive(true);
|
|
||||||
sendRequest.setDriveSync(true);
|
|
||||||
sendRequest.setAccount(account);
|
|
||||||
checkPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks permissions to needed Google services.
|
|
||||||
*/
|
|
||||||
private void checkPermissions() {
|
|
||||||
// Check Drive permission
|
|
||||||
boolean needDrivePermission = sendRequest.isSendDrive();
|
|
||||||
if (!needDrivePermission && sendRequest.isSendFusionTables()) {
|
|
||||||
needDrivePermission = PreferencesUtils.getBoolean(this,
|
|
||||||
R.string.export_google_fusion_tables_public_key,
|
|
||||||
PreferencesUtils.EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT);
|
|
||||||
}
|
|
||||||
if (!needDrivePermission) {
|
|
||||||
needDrivePermission = sendRequest.isSendSpreadsheets();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needDrivePermission) {
|
|
||||||
startCheckPermission(SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
} else {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts checking permission for a Google service.
|
|
||||||
*
|
|
||||||
* @param scope the service scope
|
|
||||||
*/
|
|
||||||
private void startCheckPermission(String scope) {
|
|
||||||
asyncTask = new CheckPermissionAsyncTask(this, sendRequest.getAccount().name, scope);
|
|
||||||
asyncTask.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
|
|
||||||
asyncTask = null;
|
|
||||||
if (success) {
|
|
||||||
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
} else if (scope.equals(SendToGoogleUtils.FUSION_TABLES_SCOPE)) {
|
|
||||||
onFusionTablesSuccess();
|
|
||||||
} else {
|
|
||||||
onSpreadsheetsPermissionSuccess();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (userRecoverableIntent != null) {
|
|
||||||
int requestCode;
|
|
||||||
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
|
|
||||||
requestCode = DRIVE_REQUEST_CODE;
|
|
||||||
} else if (scope.equals(SendToGoogleUtils.FUSION_TABLES_SCOPE)) {
|
|
||||||
requestCode = FUSION_TABLES_REQUEST_CODE;
|
|
||||||
} else {
|
|
||||||
requestCode = SPREADSHEETS_REQUEST_CODE;
|
|
||||||
}
|
|
||||||
startActivityForResult(userRecoverableIntent, requestCode);
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrivePermissionSuccess() {
|
|
||||||
// Check Maps permission
|
|
||||||
if (sendRequest.isSendMaps()) {
|
|
||||||
AccountManager.get(this).getAuthToken(
|
|
||||||
sendRequest.getAccount(), MapsConstants.SERVICE_NAME, null, this,
|
|
||||||
new AccountManagerCallback<Bundle>() {
|
|
||||||
@Override
|
|
||||||
public void run(AccountManagerFuture<Bundle> future) {
|
|
||||||
try {
|
|
||||||
if (future.getResult().getString(AccountManager.KEY_AUTHTOKEN) != null) {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onMapsPermissionSuccess();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "auth token is null");
|
|
||||||
}
|
|
||||||
} catch (OperationCanceledException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
} catch (AuthenticatorException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
}
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
} else {
|
|
||||||
onMapsPermissionSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onMapsPermissionSuccess() {
|
|
||||||
// Check Fusion Tables permission
|
|
||||||
if (sendRequest.isSendFusionTables()) {
|
|
||||||
startCheckPermission(SendToGoogleUtils.FUSION_TABLES_SCOPE);
|
|
||||||
} else {
|
|
||||||
onFusionTablesSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFusionTablesSuccess() {
|
|
||||||
// Check Spreadsheets permission
|
|
||||||
if (sendRequest.isSendSpreadsheets()) {
|
|
||||||
startCheckPermission(SendToGoogleUtils.SPREADSHEETS_SCOPE);
|
|
||||||
} else {
|
|
||||||
onSpreadsheetsPermissionSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On spreadsheets permission success. If
|
|
||||||
* <p>
|
|
||||||
* isSendDrive and isDriveEnableSync -> enable sync
|
|
||||||
* <p>
|
|
||||||
* isSendDrive -> start {@link SendDriveActivity}
|
|
||||||
* <p>
|
|
||||||
* isSendMaps -> start {@link SendMapsActivity}
|
|
||||||
* <p>
|
|
||||||
* isSendFusionTables -> start {@link SendFusionTablesActivity}
|
|
||||||
* <p>
|
|
||||||
* isSendSpreadsheets -> start {@link SendSpreadsheetsActivity}
|
|
||||||
* <p>
|
|
||||||
* else -> start {@link UploadResultActivity}
|
|
||||||
*/
|
|
||||||
private void onSpreadsheetsPermissionSuccess() {
|
|
||||||
Class<?> next;
|
|
||||||
if (sendRequest.isSendDrive()) {
|
|
||||||
if (sendRequest.isDriveSync()) {
|
|
||||||
SyncUtils.enableSync(this);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
next = SendDriveActivity.class;
|
|
||||||
}
|
|
||||||
} else if (sendRequest.isSendMaps()) {
|
|
||||||
next = SendMapsActivity.class;
|
|
||||||
} else if (sendRequest.isSendFusionTables()) {
|
|
||||||
next = SendFusionTablesActivity.class;
|
|
||||||
} else if (sendRequest.isSendSpreadsheets()) {
|
|
||||||
next = SendSpreadsheetsActivity.class;
|
|
||||||
} else {
|
|
||||||
next = UploadResultActivity.class;
|
|
||||||
}
|
|
||||||
Intent intent = IntentUtils.newIntent(this, next)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call when not able to get permission for a google service.
|
* Call when not able to get permission for a google service.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtil
|
|||||||
import com.google.android.gms.location.LocationListener;
|
import com.google.android.gms.location.LocationListener;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.app.SearchManager;
|
import android.app.SearchManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -556,4 +557,9 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -493,8 +493,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
|||||||
.putExtra(SaveActivity.EXTRA_TRACK_IDS, new long[] { trackId })
|
.putExtra(SaveActivity.EXTRA_TRACK_IDS, new long[] { trackId })
|
||||||
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
|
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else {
|
|
||||||
exportTrackToGoogle(trackId, exportType, account);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,4 +638,9 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
|||||||
new MapLayerDialogFragment().show(
|
new MapLayerDialogFragment().show(
|
||||||
getSupportFragmentManager(), MapLayerDialogFragment.MAP_LAYER_DIALOG_TAG);
|
getSupportFragmentManager(), MapLayerDialogFragment.MAP_LAYER_DIALOG_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,6 @@ import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragme
|
|||||||
import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
|
import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
|
||||||
import com.google.android.apps.mytracks.fragments.EnableSyncDialogFragment;
|
import com.google.android.apps.mytracks.fragments.EnableSyncDialogFragment;
|
||||||
import com.google.android.apps.mytracks.fragments.EnableSyncDialogFragment.EnableSyncCaller;
|
import com.google.android.apps.mytracks.fragments.EnableSyncDialogFragment.EnableSyncCaller;
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||||
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
||||||
@@ -218,20 +217,6 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
|||||||
return syncDriveAsyncTask;
|
return syncDriveAsyncTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
if (requestCode == DRIVE_REQUEST_CODE) {
|
|
||||||
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
@@ -281,36 +266,11 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChooseAccountDone(String account) {
|
public void onChooseAccountDone(String account) {
|
||||||
PreferencesUtils.setString(this, R.string.google_account_key, account);
|
|
||||||
if (PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT.equals(account)) {
|
|
||||||
finish();
|
|
||||||
} else {
|
|
||||||
syncDriveAsyncTask = new CheckPermissionAsyncTask(this, account, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
syncDriveAsyncTask.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
|
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
|
||||||
syncDriveAsyncTask = null;
|
|
||||||
if (success) {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
} else {
|
|
||||||
if (userRecoverableIntent != null) {
|
|
||||||
startActivityForResult(userRecoverableIntent, DRIVE_REQUEST_CODE);
|
|
||||||
} else {
|
|
||||||
onPermissionFailure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrivePermissionSuccess() {
|
|
||||||
SyncUtils.enableSync(this);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onPermissionFailure() {
|
|
||||||
Toast.makeText(this, R.string.send_google_no_account_permission, Toast.LENGTH_LONG).show();
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -808,7 +808,12 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
|||||||
if (enable) {
|
if (enable) {
|
||||||
String googleAccount = PreferencesUtils.getString(
|
String googleAccount = PreferencesUtils.getString(
|
||||||
this, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
this, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||||
enableSync(new Account(googleAccount, Constants.ACCOUNT_TYPE));
|
//enableSync(new Account(googleAccount, Constants.ACCOUNT_TYPE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 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 com.google.android.apps.mytracks.io.drive;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.maps.SendMapsActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An activity to send a track to Google Drive.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendDriveActivity extends AbstractSendActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractSendAsyncTask createAsyncTask() {
|
|
||||||
return new SendDriveAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount(),
|
|
||||||
sendRequest.getDriveShareEmails(), sendRequest.isDriveSharePublic());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getServiceName() {
|
|
||||||
return getString(R.string.export_google_drive);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void startNextActivity(boolean success, boolean isCancel) {
|
|
||||||
sendRequest.setDriveSuccess(success);
|
|
||||||
Class<?> next = getNextClass(isCancel);
|
|
||||||
Intent intent = IntentUtils.newIntent(this, next)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> getNextClass(boolean isCancel) {
|
|
||||||
if (isCancel) {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
} else {
|
|
||||||
if (sendRequest.isSendMaps()) {
|
|
||||||
return SendMapsActivity.class;
|
|
||||||
} else if (sendRequest.isSendFusionTables()) {
|
|
||||||
return SendFusionTablesActivity.class;
|
|
||||||
} else if (sendRequest.isSendSpreadsheets()) {
|
|
||||||
return SendSpreadsheetsActivity.class;
|
|
||||||
} else {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-198
@@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 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 com.google.android.apps.mytracks.io.drive;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
|
||||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
|
||||||
import com.google.api.services.drive.Drive;
|
|
||||||
import com.google.api.services.drive.model.File;
|
|
||||||
import com.google.api.services.drive.model.Permission;
|
|
||||||
import com.google.api.services.drive.model.PermissionList;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AsyncTask to send a track to Google Drive.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendDriveAsyncTask extends AbstractSendAsyncTask {
|
|
||||||
|
|
||||||
private final long trackId;
|
|
||||||
private final Account account;
|
|
||||||
private final String[] acl;
|
|
||||||
private final boolean isPublic;
|
|
||||||
private final Context context;
|
|
||||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
|
||||||
|
|
||||||
public SendDriveAsyncTask(
|
|
||||||
SendDriveActivity activity, long trackId, Account account, String acl, boolean isPublic) {
|
|
||||||
super(activity);
|
|
||||||
this.trackId = trackId;
|
|
||||||
this.account = account;
|
|
||||||
if (acl != null) {
|
|
||||||
this.acl = acl.split(",");
|
|
||||||
} else {
|
|
||||||
this.acl = null;
|
|
||||||
}
|
|
||||||
this.isPublic = isPublic;
|
|
||||||
|
|
||||||
context = activity.getApplicationContext();
|
|
||||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void closeConnection() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performTask() {
|
|
||||||
try {
|
|
||||||
GoogleAccountCredential credential = SendToGoogleUtils.getGoogleAccountCredential(
|
|
||||||
context, account.name, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
if (credential == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Drive drive = SyncUtils.getDriveService(credential);
|
|
||||||
File folder = SyncUtils.getMyTracksFolder(context, drive);
|
|
||||||
if (folder == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String folderId = folder.getId();
|
|
||||||
if (folderId == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Track track = myTracksProviderUtils.getTrack(trackId);
|
|
||||||
String driveId = track.getDriveId();
|
|
||||||
String syncAccount = PreferencesUtils.getString(
|
|
||||||
context, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
|
||||||
boolean sameAccount = account.name.equals(syncAccount);
|
|
||||||
if (sameAccount && driveId != null && !driveId.equals("")) {
|
|
||||||
File driveFile = drive.files().get(driveId).execute();
|
|
||||||
if (driveFile != null && updateDriveFile(drive, driveFile, folderId, track)) {
|
|
||||||
addPermission(drive, driveFile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear sync state
|
|
||||||
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert new drive file
|
|
||||||
File file = SyncUtils.insertDriveFile(
|
|
||||||
drive, folderId, context, myTracksProviderUtils, track, false, sameAccount);
|
|
||||||
if (file == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
addPermission(drive, file);
|
|
||||||
return true;
|
|
||||||
} catch (UserRecoverableAuthException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (GoogleAuthException e) {
|
|
||||||
return retryTask();
|
|
||||||
} catch (UserRecoverableAuthIOException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a drive file using info from a track. Returns true if successful.
|
|
||||||
*
|
|
||||||
* @param drive the drive
|
|
||||||
* @param driveFile the drive file
|
|
||||||
* @param folderId the folder id of the drive file
|
|
||||||
* @param track the track
|
|
||||||
*/
|
|
||||||
private boolean updateDriveFile(Drive drive, File driveFile, String folderId, Track track)
|
|
||||||
throws IOException {
|
|
||||||
if (!SyncUtils.isInMyTracksAndValid(driveFile, folderId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
long driveModifiedTime = driveFile.getModifiedDate().getValue();
|
|
||||||
long modifiedTime = track.getModifiedTime();
|
|
||||||
|
|
||||||
if (driveModifiedTime != modifiedTime) {
|
|
||||||
return SyncUtils.updateDriveFile(
|
|
||||||
drive, driveFile, context, myTracksProviderUtils, track, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidateToken() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds permission.
|
|
||||||
*
|
|
||||||
* @param drive the drive
|
|
||||||
* @param file the drive file
|
|
||||||
*/
|
|
||||||
private void addPermission(Drive drive, File file) throws IOException {
|
|
||||||
if (isPublic) {
|
|
||||||
boolean hasPublic = false;
|
|
||||||
PermissionList permissionList = drive.permissions().list(file.getId()).execute();
|
|
||||||
for (Permission permission : permissionList.getItems()) {
|
|
||||||
String role = permission.getRole();
|
|
||||||
if (role.equals("reader") || role.equals("writer")) {
|
|
||||||
if (permission.getType().equals("anyone")) {
|
|
||||||
hasPublic = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasPublic) {
|
|
||||||
Permission permission = new Permission();
|
|
||||||
permission.setRole("reader");
|
|
||||||
permission.setType("anyone");
|
|
||||||
permission.setValue("");
|
|
||||||
drive.permissions().insert(file.getId(), permission).execute();
|
|
||||||
}
|
|
||||||
shareUrl = file.getAlternateLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acl != null) {
|
|
||||||
for (String email : acl) {
|
|
||||||
email = email.trim();
|
|
||||||
if (!email.equals("")) {
|
|
||||||
Permission permission = new Permission();
|
|
||||||
permission.setRole("reader");
|
|
||||||
permission.setType("user");
|
|
||||||
permission.setValue(email);
|
|
||||||
drive.permissions().insert(file.getId(), permission).execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-69
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.fusiontables;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An activity to send a track to Google Fusion Tables.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendFusionTablesActivity extends AbstractSendActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractSendAsyncTask createAsyncTask() {
|
|
||||||
return new SendFusionTablesAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getServiceName() {
|
|
||||||
return getString(R.string.export_google_fusion_tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void startNextActivity(boolean success, boolean isCancel) {
|
|
||||||
sendRequest.setFusionTablesSuccess(success);
|
|
||||||
Class<?> next = getNextClass(sendRequest, isCancel);
|
|
||||||
Intent intent = IntentUtils.newIntent(this, next)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
Class<?> getNextClass(SendRequest request, boolean isCancel) {
|
|
||||||
if (isCancel) {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
} else {
|
|
||||||
if (request.isSendSpreadsheets()) {
|
|
||||||
return SendSpreadsheetsActivity.class;
|
|
||||||
} else {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-402
@@ -1,402 +0,0 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
|
||||||
|
|
||||||
package com.google.android.apps.mytracks.io.fusiontables;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
|
||||||
import com.google.android.apps.mytracks.content.DescriptionGenerator;
|
|
||||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
|
||||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.api.client.extensions.android.http.AndroidHttp;
|
|
||||||
import com.google.api.client.googleapis.GoogleUrl;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
|
||||||
import com.google.api.client.http.ByteArrayContent;
|
|
||||||
import com.google.api.client.http.HttpContent;
|
|
||||||
import com.google.api.client.json.gson.GsonFactory;
|
|
||||||
import com.google.api.services.drive.Drive;
|
|
||||||
import com.google.api.services.drive.model.Permission;
|
|
||||||
import com.google.api.services.fusiontables.Fusiontables;
|
|
||||||
import com.google.api.services.fusiontables.Fusiontables.Query.Sql;
|
|
||||||
import com.google.api.services.fusiontables.model.Column;
|
|
||||||
import com.google.api.services.fusiontables.model.PointStyle;
|
|
||||||
import com.google.api.services.fusiontables.model.StyleFunction;
|
|
||||||
import com.google.api.services.fusiontables.model.StyleSetting;
|
|
||||||
import com.google.api.services.fusiontables.model.Table;
|
|
||||||
import com.google.api.services.fusiontables.model.Template;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AsyncTask to send a track to Google Fusion Tables.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
|
|
||||||
|
|
||||||
private static final String TAG = SendFusionTablesAsyncTask.class.getSimpleName();
|
|
||||||
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
|
||||||
private static final int PROGRESS_CREATE_TABLE = 0;
|
|
||||||
private static final int PROGRESS_SET_STYLE = 5;
|
|
||||||
private static final int PROGRESS_UPLOAD_DATA_MIN = 10;
|
|
||||||
private static final int PROGRESS_UPLOAD_DATA_MAX = 90;
|
|
||||||
private static final int PROGRESS_UPLOAD_WAYPOINTS = 95;
|
|
||||||
private static final int PROGRESS_COMPLETE = 100;
|
|
||||||
|
|
||||||
// See
|
|
||||||
// http://support.google.com/fusiontables/bin/answer.py?hl=en&answer=185991
|
|
||||||
private static final String MARKER_TYPE_START = "large_green";
|
|
||||||
private static final String MARKER_TYPE_END = "large_red";
|
|
||||||
private static final String MARKER_TYPE_WAYPOINT = "large_blue";
|
|
||||||
private static final String MARKER_TYPE_STATISTICS = "large_yellow";
|
|
||||||
|
|
||||||
private final long trackId;
|
|
||||||
private final Account account;
|
|
||||||
private final Context context;
|
|
||||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
|
||||||
|
|
||||||
int currentSegment;
|
|
||||||
|
|
||||||
public SendFusionTablesAsyncTask(
|
|
||||||
SendFusionTablesActivity activity, long trackId, Account account) {
|
|
||||||
super(activity);
|
|
||||||
this.trackId = trackId;
|
|
||||||
this.account = account;
|
|
||||||
context = activity.getApplicationContext();
|
|
||||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void closeConnection() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performTask() {
|
|
||||||
try {
|
|
||||||
// Reset the per upload states
|
|
||||||
currentSegment = 1;
|
|
||||||
|
|
||||||
GoogleAccountCredential credential = SendToGoogleUtils.getGoogleAccountCredential(
|
|
||||||
context, account.name, SendToGoogleUtils.FUSION_TABLES_SCOPE);
|
|
||||||
if (credential == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Fusiontables fusiontables = new Fusiontables.Builder(
|
|
||||||
AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential).build();
|
|
||||||
|
|
||||||
Track track = myTracksProviderUtils.getTrack(trackId);
|
|
||||||
if (track == null) {
|
|
||||||
Log.d(TAG, "No track for " + trackId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new table
|
|
||||||
publishProgress(PROGRESS_CREATE_TABLE);
|
|
||||||
String tableId = createNewTable(fusiontables, track);
|
|
||||||
if (tableId == null) {
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_SET_STYLE);
|
|
||||||
setStyle(fusiontables, tableId);
|
|
||||||
setTemplate(fusiontables, tableId);
|
|
||||||
if (!setPermission(track, tableId)) {
|
|
||||||
Log.d(TAG, "Cannot set permission for table " + tableId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload all the track points plus the start and end markers
|
|
||||||
publishProgress(PROGRESS_UPLOAD_DATA_MIN);
|
|
||||||
if (!uploadAllTrackPoints(fusiontables, tableId, track)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload all the waypoints
|
|
||||||
publishProgress(PROGRESS_UPLOAD_WAYPOINTS);
|
|
||||||
if (!uploadWaypoints(fusiontables, tableId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_COMPLETE);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} catch (UserRecoverableAuthException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.FUSION_TABLES_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (GoogleAuthException e) {
|
|
||||||
return retryTask();
|
|
||||||
} catch (UserRecoverableAuthIOException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.FUSION_TABLES_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidateToken() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new table.
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param track the track
|
|
||||||
* @return the table id if success.
|
|
||||||
*/
|
|
||||||
private String createNewTable(Fusiontables fusiontables, Track track) throws IOException {
|
|
||||||
Table table = new Table();
|
|
||||||
table.setName(track.getName());
|
|
||||||
table.setDescription(track.getDescription());
|
|
||||||
table.setIsExportable(true);
|
|
||||||
table.setColumns(Arrays.asList(new Column().setName("name").setType("STRING"),
|
|
||||||
new Column().setName("description").setType("STRING"),
|
|
||||||
new Column().setName("geometry").setType("LOCATION"),
|
|
||||||
new Column().setName("icon").setType("STRING")));
|
|
||||||
return fusiontables.table().insert(table).execute().getTableId();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setStyle(Fusiontables fusiontables, String tableId) throws IOException {
|
|
||||||
StyleFunction styleFunction = new StyleFunction();
|
|
||||||
styleFunction.setColumnName("icon");
|
|
||||||
PointStyle pointStyle = new PointStyle();
|
|
||||||
pointStyle.setIconStyler(styleFunction);
|
|
||||||
StyleSetting styleSetting = new StyleSetting();
|
|
||||||
styleSetting.setTableId(tableId);
|
|
||||||
styleSetting.setMarkerOptions(pointStyle);
|
|
||||||
|
|
||||||
fusiontables.style().insert(tableId, styleSetting).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTemplate(Fusiontables fusiontables, String tableId) throws IOException {
|
|
||||||
Template template = new Template();
|
|
||||||
template.setTableId(tableId);
|
|
||||||
template.setAutomaticColumnNames(Arrays.asList("name", "description"));
|
|
||||||
fusiontables.template().insert(tableId, template).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setPermission(Track track, String tableId) throws IOException, GoogleAuthException {
|
|
||||||
boolean defaultTablePublic = PreferencesUtils.getBoolean(context,
|
|
||||||
R.string.export_google_fusion_tables_public_key,
|
|
||||||
PreferencesUtils.EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT);
|
|
||||||
if (!defaultTablePublic) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
GoogleAccountCredential driveCredential = SendToGoogleUtils.getGoogleAccountCredential(
|
|
||||||
context, account.name, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
if (driveCredential == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Drive drive = SyncUtils.getDriveService(driveCredential);
|
|
||||||
Permission permission = new Permission();
|
|
||||||
permission.setRole("reader");
|
|
||||||
permission.setType("anyone");
|
|
||||||
permission.setValue("");
|
|
||||||
drive.permissions().insert(tableId, permission).execute();
|
|
||||||
|
|
||||||
shareUrl = SendFusionTablesUtils.getMapUrl(track, tableId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads all the points in a track. *
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param tableId the table id
|
|
||||||
* @param track the track
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
private boolean uploadAllTrackPoints(Fusiontables fusiontables, String tableId, Track track)
|
|
||||||
throws IOException {
|
|
||||||
int numberOfPoints = track.getNumberOfPoints();
|
|
||||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
|
||||||
Location lastValidLocation = null;
|
|
||||||
boolean sentStartMarker = false;
|
|
||||||
int readCount = 0;
|
|
||||||
|
|
||||||
LocationIterator locationIterator = null;
|
|
||||||
try {
|
|
||||||
locationIterator = myTracksProviderUtils.getTrackPointLocationIterator(
|
|
||||||
trackId, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
|
||||||
|
|
||||||
while (locationIterator.hasNext()) {
|
|
||||||
Location location = locationIterator.next();
|
|
||||||
locations.add(location);
|
|
||||||
|
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
|
||||||
lastValidLocation = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sentStartMarker && lastValidLocation != null) {
|
|
||||||
// Create a start marker
|
|
||||||
String name = context.getString(R.string.marker_label_start, track.getName());
|
|
||||||
createNewPoint(fusiontables, tableId, name, "", lastValidLocation, MARKER_TYPE_START);
|
|
||||||
sentStartMarker = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload periodically
|
|
||||||
readCount++;
|
|
||||||
if (readCount % MAX_POINTS_PER_UPLOAD == 0) {
|
|
||||||
if (!prepareAndUploadPoints(fusiontables, tableId, track, locations, false)) {
|
|
||||||
Log.d(TAG, "Unable to upload points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
updateProgress(readCount, numberOfPoints);
|
|
||||||
locations.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a final upload with the remaining locations
|
|
||||||
if (!prepareAndUploadPoints(fusiontables, tableId, track, locations, true)) {
|
|
||||||
Log.d(TAG, "Unable to upload points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an end marker
|
|
||||||
if (lastValidLocation != null) {
|
|
||||||
String name = context.getString(R.string.marker_label_end, track.getName());
|
|
||||||
DescriptionGenerator descriptionGenerator = new DescriptionGeneratorImpl(context);
|
|
||||||
String description = descriptionGenerator.generateTrackDescription(track, null, null, true);
|
|
||||||
createNewPoint(
|
|
||||||
fusiontables, tableId, name, description, lastValidLocation, MARKER_TYPE_END);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (locationIterator != null) {
|
|
||||||
locationIterator.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares and uploads a list of locations from a track.
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param tableId the table id
|
|
||||||
* @param track the track
|
|
||||||
* @param locations the locations from the track
|
|
||||||
* @param lastBatch true if it is the last batch of locations
|
|
||||||
*/
|
|
||||||
private boolean prepareAndUploadPoints(Fusiontables fusiontables, String tableId, Track track,
|
|
||||||
List<Location> locations, boolean lastBatch) throws IOException {
|
|
||||||
// Prepare locations
|
|
||||||
ArrayList<Track> splitTracks = SendToGoogleUtils.prepareLocations(track, locations);
|
|
||||||
|
|
||||||
// Upload segments
|
|
||||||
boolean onlyOneSegment = lastBatch && currentSegment == 1 && splitTracks.size() == 1;
|
|
||||||
for (Track splitTrack : splitTracks) {
|
|
||||||
if (!onlyOneSegment) {
|
|
||||||
splitTrack.setName(context.getString(
|
|
||||||
R.string.send_google_track_part_label, splitTrack.getName(), currentSegment));
|
|
||||||
}
|
|
||||||
createNewLineString(fusiontables, tableId, splitTrack);
|
|
||||||
currentSegment++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads all the waypoints.
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param tableId the table id
|
|
||||||
* @return true if success.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private boolean uploadWaypoints(Fusiontables fusiontables, String tableId) throws IOException {
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = myTracksProviderUtils.getWaypointCursor(
|
|
||||||
trackId, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
/*
|
|
||||||
* This will skip the first waypoint (it carries the stats for the
|
|
||||||
* track).
|
|
||||||
*/
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
Waypoint wpt = myTracksProviderUtils.createWaypoint(cursor);
|
|
||||||
String type = wpt.getType() == WaypointType.STATISTICS ? MARKER_TYPE_STATISTICS
|
|
||||||
: MARKER_TYPE_WAYPOINT;
|
|
||||||
String description = wpt.getDescription().replaceAll("\n", "<br>");
|
|
||||||
createNewPoint(
|
|
||||||
fusiontables, tableId, wpt.getName(), description, wpt.getLocation(), type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new row in Google Fusion Tables representing a marker as a point.
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param tableId the table id
|
|
||||||
* @param name the marker name
|
|
||||||
* @param description the marker description
|
|
||||||
* @param location the marker location
|
|
||||||
* @param type the marker type
|
|
||||||
*/
|
|
||||||
private void createNewPoint(Fusiontables fusiontables, String tableId, String name,
|
|
||||||
String description, Location location, String type) throws IOException {
|
|
||||||
String values = SendFusionTablesUtils.formatSqlValues(
|
|
||||||
name, description, SendFusionTablesUtils.getKmlPoint(location), type);
|
|
||||||
Sql sql = fusiontables.query()
|
|
||||||
.sql("INSERT INTO " + tableId + " (name,description,geometry,icon) VALUES " + values);
|
|
||||||
sql.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new row in Google Fusion Tables representing the track as a line
|
|
||||||
* segment.
|
|
||||||
*
|
|
||||||
* @param fusiontables fusion tables
|
|
||||||
* @param tableId the table id
|
|
||||||
* @param track the track
|
|
||||||
*/
|
|
||||||
private void createNewLineString(Fusiontables fusiontables, String tableId, Track track)
|
|
||||||
throws IOException {
|
|
||||||
String values = SendFusionTablesUtils.formatSqlValues(track.getName(), track.getDescription(),
|
|
||||||
SendFusionTablesUtils.getKmlLineString(track.getLocations()));
|
|
||||||
String sql = "INSERT INTO " + tableId + " (name,description,geometry) VALUES " + values;
|
|
||||||
HttpContent content = ByteArrayContent.fromString(null, "sql=" + sql);
|
|
||||||
GoogleUrl url = new GoogleUrl("https://www.googleapis.com/fusiontables/v1/query");
|
|
||||||
fusiontables.getRequestFactory().buildPostRequest(url, content).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the progress based on the number of locations uploaded.
|
|
||||||
*
|
|
||||||
* @param uploaded the number of uploaded locations
|
|
||||||
* @param total the number of total locations
|
|
||||||
*/
|
|
||||||
private void updateProgress(int uploaded, int total) {
|
|
||||||
double totalPercentage = (double) uploaded / total;
|
|
||||||
double scaledPercentage = totalPercentage
|
|
||||||
* (PROGRESS_UPLOAD_DATA_MAX - PROGRESS_UPLOAD_DATA_MIN) + PROGRESS_UPLOAD_DATA_MIN;
|
|
||||||
publishProgress((int) scaledPercentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-155
@@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.fusiontables;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for sending a track to Google Fusion Tables.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendFusionTablesUtils {
|
|
||||||
|
|
||||||
private static final String MAP_URL = "https://www.google.com/fusiontables/embedviz?"
|
|
||||||
+ "viz=MAP&q=select+col0,+col1,+col2,+col3+from+%s+&h=false&lat=%f&lng=%f&z=%d&t=1&l=col2";
|
|
||||||
private static final String TAG = SendFusionTablesUtils.class.getSimpleName();
|
|
||||||
|
|
||||||
private SendFusionTablesUtils() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the url to visualize a fusion table on a map.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
* @param tableId the table id
|
|
||||||
* @return the url.
|
|
||||||
*/
|
|
||||||
public static String getMapUrl(Track track, String tableId) {
|
|
||||||
if (track == null || track.getTripStatistics() == null) {
|
|
||||||
Log.e(TAG, "Invalid track");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
double latE6;
|
|
||||||
double lonE6;
|
|
||||||
int z;
|
|
||||||
if (track.getNumberOfPoints() < 2) {
|
|
||||||
// Use Google's latitude and longitude
|
|
||||||
latE6 = 37.423 * 1.E6;
|
|
||||||
lonE6 = -122.084 * 1.E6;
|
|
||||||
z = 2;
|
|
||||||
} else {
|
|
||||||
TripStatistics stats = track.getTripStatistics();
|
|
||||||
latE6 = stats.getBottom() + (stats.getTop() - stats.getBottom()) / 2;
|
|
||||||
lonE6 = stats.getLeft() + (stats.getRight() - stats.getLeft()) / 2;
|
|
||||||
z = 15;
|
|
||||||
}
|
|
||||||
// We explicitly format with Locale.US because we need the latitude and
|
|
||||||
// longitude to be formatted in a locale-independent manner. Specifically,
|
|
||||||
// we need the decimal separator to be a period rather than a comma.
|
|
||||||
return String.format(Locale.US, MAP_URL, tableId, latE6 / 1.E6, lonE6 / 1.E6, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats an array of values as a SQL VALUES like
|
|
||||||
* ('value1','value2',...,'value_n'). Escapes single quotes with two single
|
|
||||||
* quotes.
|
|
||||||
*
|
|
||||||
* @param values an array of values to format
|
|
||||||
* @return the formated SQL VALUES.
|
|
||||||
*/
|
|
||||||
public static String formatSqlValues(String... values) {
|
|
||||||
StringBuilder builder = new StringBuilder("(");
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
builder.append(',');
|
|
||||||
}
|
|
||||||
builder.append('\'');
|
|
||||||
builder.append(escapeSqlString(values[i]));
|
|
||||||
builder.append('\'');
|
|
||||||
}
|
|
||||||
builder.append(")");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes a SQL string. Escapes single quotes with two single quotes.
|
|
||||||
*
|
|
||||||
* @param string the string
|
|
||||||
* @return the escaped string.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static String escapeSqlString(String string) {
|
|
||||||
return string.replaceAll("'", "''");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a KML Point value representing a location.
|
|
||||||
*
|
|
||||||
* @param location the location
|
|
||||||
* @return the KML Point value.
|
|
||||||
*/
|
|
||||||
public static String getKmlPoint(Location location) {
|
|
||||||
StringBuilder builder = new StringBuilder("<Point><coordinates>");
|
|
||||||
if (location != null) {
|
|
||||||
appendLocation(location, builder);
|
|
||||||
}
|
|
||||||
builder.append("</coordinates></Point>");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a KML LineString value representing an array of locations.
|
|
||||||
*
|
|
||||||
* @param locations the locations.
|
|
||||||
* @return the KML LineString value.
|
|
||||||
*/
|
|
||||||
public static String getKmlLineString(ArrayList<Location> locations) {
|
|
||||||
StringBuilder builder = new StringBuilder("<LineString><coordinates>");
|
|
||||||
if (locations != null) {
|
|
||||||
for (int i = 0; i < locations.size(); i++) {
|
|
||||||
if (i != 0) {
|
|
||||||
builder.append(' ');
|
|
||||||
}
|
|
||||||
appendLocation(locations.get(i), builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.append("</coordinates></LineString>");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a location to a string builder using "longitude,latitude[,altitude]" format.
|
|
||||||
*
|
|
||||||
* @param location the location
|
|
||||||
* @param builder the string builder
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static void appendLocation(Location location, StringBuilder builder) {
|
|
||||||
builder.append(location.getLongitude()).append(",").append(location.getLatitude());
|
|
||||||
if (location.hasAltitude()) {
|
|
||||||
builder.append(",");
|
|
||||||
builder.append(location.getAltitude());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-457
@@ -1,457 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 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 com.google.android.apps.mytracks.io.gdata;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.client.GDataClient;
|
|
||||||
import com.google.wireless.gdata.client.HttpException;
|
|
||||||
import com.google.wireless.gdata.client.QueryParams;
|
|
||||||
import com.google.wireless.gdata.data.StringUtils;
|
|
||||||
import com.google.wireless.gdata.parser.ParseException;
|
|
||||||
import com.google.wireless.gdata.serializer.GDataSerializer;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.zip.GZIPInputStream;
|
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
|
||||||
import org.apache.http.entity.AbstractHttpEntity;
|
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
|
||||||
import org.apache.http.entity.InputStreamEntity;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of a GDataClient using GoogleHttpClient to make HTTP requests.
|
|
||||||
* Always issues GETs and POSTs, using the X-HTTP-Method-Override header when a
|
|
||||||
* PUT or DELETE is desired, to avoid issues with firewalls, etc., that do not
|
|
||||||
* allow methods other than GET or POST.
|
|
||||||
*/
|
|
||||||
public class AndroidGDataClient implements GDataClient {
|
|
||||||
|
|
||||||
private static final String TAG = "GDataClient";
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
|
|
||||||
|
|
||||||
private static final int MAX_REDIRECTS = 10;
|
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for creating HTTP requests. Used by
|
|
||||||
* {@link AndroidGDataClient#createAndExecuteMethod}, since HttpUriRequest
|
|
||||||
* does not allow for changing the URI after creation, e.g., when you want to
|
|
||||||
* follow a redirect.
|
|
||||||
*/
|
|
||||||
private interface HttpRequestCreator {
|
|
||||||
HttpUriRequest createRequest(URI uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class GetRequestCreator implements HttpRequestCreator {
|
|
||||||
public HttpUriRequest createRequest(URI uri) {
|
|
||||||
return new HttpGet(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PostRequestCreator implements HttpRequestCreator {
|
|
||||||
private final String mMethodOverride;
|
|
||||||
private final HttpEntity mEntity;
|
|
||||||
|
|
||||||
public PostRequestCreator(String methodOverride, HttpEntity entity) {
|
|
||||||
mMethodOverride = methodOverride;
|
|
||||||
mEntity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUriRequest createRequest(URI uri) {
|
|
||||||
HttpPost post = new HttpPost(uri);
|
|
||||||
if (mMethodOverride != null) {
|
|
||||||
post.addHeader(X_HTTP_METHOD_OVERRIDE, mMethodOverride);
|
|
||||||
}
|
|
||||||
post.setEntity(mEntity);
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MAJOR TODO: make this work across redirects (if we can reset the
|
|
||||||
// InputStream).
|
|
||||||
// OR, read the bits into a local buffer (yuck, the media could be large).
|
|
||||||
private static class MediaPutRequestCreator implements HttpRequestCreator {
|
|
||||||
private final InputStream mMediaInputStream;
|
|
||||||
private final String mContentType;
|
|
||||||
|
|
||||||
public MediaPutRequestCreator(InputStream mediaInputStream,
|
|
||||||
String contentType) {
|
|
||||||
mMediaInputStream = mediaInputStream;
|
|
||||||
mContentType = contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUriRequest createRequest(URI uri) {
|
|
||||||
HttpPost post = new HttpPost(uri);
|
|
||||||
post.addHeader(X_HTTP_METHOD_OVERRIDE, "PUT");
|
|
||||||
InputStreamEntity entity =
|
|
||||||
new InputStreamEntity(mMediaInputStream, -1 /* read until EOF */);
|
|
||||||
entity.setContentType(mContentType);
|
|
||||||
post.setEntity(entity);
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new AndroidGDataClient.
|
|
||||||
*/
|
|
||||||
public AndroidGDataClient() {
|
|
||||||
httpClient = new DefaultHttpClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see GDataClient#encodeUri(java.lang.String)
|
|
||||||
*/
|
|
||||||
public String encodeUri(String uri) {
|
|
||||||
String encodedUri = null;
|
|
||||||
try {
|
|
||||||
encodedUri = URLEncoder.encode(uri, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException uee) {
|
|
||||||
// Should not happen
|
|
||||||
throw new IllegalStateException("Cannot encode " + uri, uee);
|
|
||||||
}
|
|
||||||
return encodedUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see com.google.wireless.gdata.client.GDataClient#createQueryParams()
|
|
||||||
*/
|
|
||||||
public QueryParams createQueryParams() {
|
|
||||||
return new QueryParamsImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// follows redirects
|
|
||||||
private InputStream createAndExecuteMethod(HttpRequestCreator creator,
|
|
||||||
String uriString, String authToken) throws HttpException, IOException {
|
|
||||||
|
|
||||||
HttpResponse response = null;
|
|
||||||
int status = 500;
|
|
||||||
int redirectsLeft = MAX_REDIRECTS;
|
|
||||||
|
|
||||||
URI uri;
|
|
||||||
try {
|
|
||||||
uri = new URI(uriString);
|
|
||||||
} catch (URISyntaxException use) {
|
|
||||||
Log.w(TAG, "Unable to parse " + uriString + " as URI.", use);
|
|
||||||
throw new IOException("Unable to parse " + uriString + " as URI: "
|
|
||||||
+ use.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// we follow redirects ourselves, since we want to follow redirects even on
|
|
||||||
// POSTs, which
|
|
||||||
// the HTTP library does not do. following redirects ourselves also allows
|
|
||||||
// us to log
|
|
||||||
// the redirects using our own logging.
|
|
||||||
while (redirectsLeft > 0) {
|
|
||||||
|
|
||||||
HttpUriRequest request = creator.createRequest(uri);
|
|
||||||
request.addHeader("User-Agent", "Android-GData");
|
|
||||||
request.addHeader("Accept-Encoding", "gzip");
|
|
||||||
|
|
||||||
// only add the auth token if not null (to allow for GData feeds that do
|
|
||||||
// not require
|
|
||||||
// authentication.)
|
|
||||||
if (!TextUtils.isEmpty(authToken)) {
|
|
||||||
request.addHeader("Authorization", "GoogleLogin auth=" + authToken);
|
|
||||||
}
|
|
||||||
if (DEBUG) {
|
|
||||||
for (Header h : request.getAllHeaders()) {
|
|
||||||
Log.v(TAG, h.getName() + ": " + h.getValue());
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Executing " + request.getRequestLine().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
response = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
response = httpClient.execute(request);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.w(TAG, "Unable to execute HTTP request." + ioe);
|
|
||||||
throw ioe;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusLine statusLine = response.getStatusLine();
|
|
||||||
if (statusLine == null) {
|
|
||||||
Log.w(TAG, "StatusLine is null.");
|
|
||||||
throw new NullPointerException(
|
|
||||||
"StatusLine is null -- should not happen.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log.d(TAG, response.getStatusLine().toString());
|
|
||||||
for (Header h : response.getAllHeaders()) {
|
|
||||||
Log.d(TAG, h.getName() + ": " + h.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
status = statusLine.getStatusCode();
|
|
||||||
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
|
|
||||||
if ((status >= 200) && (status < 300) && entity != null) {
|
|
||||||
return getUngzippedContent(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle 301, 307?
|
|
||||||
// TODO: let the http client handle the redirects, if we can be sure we'll
|
|
||||||
// never get a
|
|
||||||
// redirect on POST.
|
|
||||||
if (status == 302) {
|
|
||||||
// consume the content, so the connection can be closed.
|
|
||||||
entity.consumeContent();
|
|
||||||
Header location = response.getFirstHeader("Location");
|
|
||||||
if (location == null) {
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log.d(TAG, "Redirect requested but no Location " + "specified.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log.d(TAG, "Following redirect to " + location.getValue());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
uri = new URI(location.getValue());
|
|
||||||
} catch (URISyntaxException use) {
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log.d(TAG, "Unable to parse " + location.getValue() + " as URI.",
|
|
||||||
use);
|
|
||||||
throw new IOException("Unable to parse " + location.getValue()
|
|
||||||
+ " as URI.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--redirectsLeft;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
|
||||||
Log.v(TAG, "Received " + status + " status code.");
|
|
||||||
}
|
|
||||||
String errorMessage = null;
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
try {
|
|
||||||
if (entity != null) {
|
|
||||||
InputStream in = entity.getContent();
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
byte[] buf = new byte[8192];
|
|
||||||
int bytesRead = -1;
|
|
||||||
while ((bytesRead = in.read(buf)) != -1) {
|
|
||||||
baos.write(buf, 0, bytesRead);
|
|
||||||
}
|
|
||||||
// TODO: use appropriate encoding, picked up from Content-Type.
|
|
||||||
errorMessage = new String(baos.toByteArray());
|
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
|
||||||
Log.v(TAG, errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (entity != null) {
|
|
||||||
entity.consumeContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String exceptionMessage = "Received " + status + " status code";
|
|
||||||
if (errorMessage != null) {
|
|
||||||
exceptionMessage += (": " + errorMessage);
|
|
||||||
}
|
|
||||||
throw new HttpException(exceptionMessage, status, null /* InputStream */);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the input stream from a response entity. If the entity is gzipped
|
|
||||||
* then this will get a stream over the uncompressed data.
|
|
||||||
*
|
|
||||||
* @param entity the entity whose content should be read
|
|
||||||
* @return the input stream to read from
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private static InputStream getUngzippedContent(HttpEntity entity)
|
|
||||||
throws IOException {
|
|
||||||
InputStream responseStream = entity.getContent();
|
|
||||||
if (responseStream == null) {
|
|
||||||
return responseStream;
|
|
||||||
}
|
|
||||||
Header header = entity.getContentEncoding();
|
|
||||||
if (header == null) {
|
|
||||||
return responseStream;
|
|
||||||
}
|
|
||||||
String contentEncoding = header.getValue();
|
|
||||||
if (contentEncoding == null) {
|
|
||||||
return responseStream;
|
|
||||||
}
|
|
||||||
if (contentEncoding.contains("gzip")){
|
|
||||||
responseStream = new GZIPInputStream(responseStream);
|
|
||||||
}
|
|
||||||
return responseStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see GDataClient#getFeedAsStream(java.lang.String, java.lang.String)
|
|
||||||
*/
|
|
||||||
public InputStream getFeedAsStream(String feedUrl, String authToken)
|
|
||||||
throws HttpException, IOException {
|
|
||||||
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(new GetRequestCreator(), feedUrl, authToken);
|
|
||||||
if (in != null) {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
throw new IOException("Unable to access feed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getMediaEntryAsStream(String mediaEntryUrl,
|
|
||||||
String authToken) throws HttpException, IOException {
|
|
||||||
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(new GetRequestCreator(), mediaEntryUrl,
|
|
||||||
authToken);
|
|
||||||
|
|
||||||
if (in != null) {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
throw new IOException("Unable to access media entry.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see GDataClient#createEntry
|
|
||||||
*/
|
|
||||||
public InputStream createEntry(String feedUrl, String authToken,
|
|
||||||
GDataSerializer entry) throws HttpException, IOException {
|
|
||||||
|
|
||||||
HttpEntity entity =
|
|
||||||
createEntityForEntry(entry, GDataSerializer.FORMAT_CREATE);
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(new PostRequestCreator(null /* override */,
|
|
||||||
entity), feedUrl, authToken);
|
|
||||||
if (in != null) {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
throw new IOException("Unable to create entry.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see GDataClient#updateEntry
|
|
||||||
*/
|
|
||||||
public InputStream updateEntry(String editUri, String authToken,
|
|
||||||
GDataSerializer entry) throws HttpException, IOException {
|
|
||||||
HttpEntity entity =
|
|
||||||
createEntityForEntry(entry, GDataSerializer.FORMAT_UPDATE);
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(new PostRequestCreator("PUT", entity), editUri,
|
|
||||||
authToken);
|
|
||||||
if (in != null) {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
throw new IOException("Unable to update entry.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see GDataClient#deleteEntry
|
|
||||||
*/
|
|
||||||
public void deleteEntry(String editUri, String authToken)
|
|
||||||
throws HttpException, IOException {
|
|
||||||
if (StringUtils.isEmpty(editUri)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"you must specify an non-empty edit url");
|
|
||||||
}
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(
|
|
||||||
new PostRequestCreator("DELETE", null /* entity */), editUri,
|
|
||||||
authToken);
|
|
||||||
if (in == null) {
|
|
||||||
throw new IOException("Unable to delete entry.");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream updateMediaEntry(String editUri, String authToken,
|
|
||||||
InputStream mediaEntryInputStream, String contentType)
|
|
||||||
throws HttpException, IOException {
|
|
||||||
InputStream in =
|
|
||||||
createAndExecuteMethod(new MediaPutRequestCreator(
|
|
||||||
mediaEntryInputStream, contentType), editUri, authToken);
|
|
||||||
if (in != null) {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
throw new IOException("Unable to write media entry.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpEntity createEntityForEntry(GDataSerializer entry, int format)
|
|
||||||
throws IOException {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
try {
|
|
||||||
entry.serialize(baos, format);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.e(TAG, "Unable to serialize entry.", ioe);
|
|
||||||
throw ioe;
|
|
||||||
} catch (ParseException pe) {
|
|
||||||
Log.e(TAG, "Unable to serialize entry.", pe);
|
|
||||||
throw new IOException("Unable to serialize entry: " + pe.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] entryBytes = baos.toByteArray();
|
|
||||||
|
|
||||||
if (entryBytes != null && Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
try {
|
|
||||||
Log.d(TAG, "Serialized entry: " + new String(entryBytes, "UTF-8"));
|
|
||||||
} catch (UnsupportedEncodingException uee) {
|
|
||||||
// should not happen
|
|
||||||
throw new IllegalStateException("UTF-8 should be supported!", uee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractHttpEntity entity = new ByteArrayEntity(entryBytes);
|
|
||||||
entity.setContentType(entry.getContentType());
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 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 com.google.android.apps.mytracks.io.gdata;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.client.GDataClient;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This factory will fetch the right class for the platform.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
public class GDataClientFactory {
|
|
||||||
|
|
||||||
private static final String TAG = GDataClientFactory.class.getSimpleName();
|
|
||||||
|
|
||||||
private GDataClientFactory() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new GData client.
|
|
||||||
* This factory will fetch the right class for the platform.
|
|
||||||
* @return A GDataClient appropriate for this platform
|
|
||||||
*/
|
|
||||||
public static GDataClient getGDataClient(Context context) {
|
|
||||||
// TODO This should be moved into ApiAdapter
|
|
||||||
try {
|
|
||||||
// Try to use the official unbundled gdata client implementation.
|
|
||||||
// This should work on Froyo and beyond.
|
|
||||||
return new com.google.android.common.gdata.AndroidGDataClient(context);
|
|
||||||
} catch (LinkageError e) {
|
|
||||||
// On all other platforms use the client implementation packaged in the
|
|
||||||
// apk.
|
|
||||||
Log.i(TAG, "Using mytracks AndroidGDataClient.", e);
|
|
||||||
return new com.google.android.apps.mytracks.io.gdata.AndroidGDataClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-103
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 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 com.google.android.apps.mytracks.io.gdata;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.client.QueryParams;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple implementation of the QueryParams interface.
|
|
||||||
*/
|
|
||||||
// TODO: deal with categories
|
|
||||||
public class QueryParamsImpl extends QueryParams {
|
|
||||||
|
|
||||||
private final Map<String, String> mParams = new HashMap<String, String>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
setEntryId(null);
|
|
||||||
mParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateQueryUrl(String feedUrl) {
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(getEntryId()) && mParams.isEmpty()) {
|
|
||||||
// nothing to do
|
|
||||||
return feedUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle entry IDs
|
|
||||||
if (!TextUtils.isEmpty(getEntryId())) {
|
|
||||||
if (!mParams.isEmpty()) {
|
|
||||||
throw new IllegalStateException("Cannot set both an entry ID "
|
|
||||||
+ "and other query paramters.");
|
|
||||||
}
|
|
||||||
return feedUrl + '/' + getEntryId();
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise, append the querystring params.
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(feedUrl);
|
|
||||||
Set<String> params = mParams.keySet();
|
|
||||||
boolean first = true;
|
|
||||||
if (feedUrl.contains("?")) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
sb.append('?');
|
|
||||||
}
|
|
||||||
for (String param : params) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
sb.append('&');
|
|
||||||
}
|
|
||||||
sb.append(param);
|
|
||||||
sb.append('=');
|
|
||||||
String value = mParams.get(param);
|
|
||||||
String encodedValue = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
encodedValue = URLEncoder.encode(value, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException uee) {
|
|
||||||
// Should not happen
|
|
||||||
throw new IllegalStateException("Cannot encode " + value, uee);
|
|
||||||
}
|
|
||||||
sb.append(encodedValue);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getParamValue(String param) {
|
|
||||||
if (!(mParams.containsKey(param))) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return mParams.get(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setParamValue(String param, String value) {
|
|
||||||
mParams.put(param, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.data.Entry;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GData entry for a map feature.
|
|
||||||
*/
|
|
||||||
public class MapFeatureEntry extends Entry {
|
|
||||||
|
|
||||||
private String mPrivacy = null;
|
|
||||||
private Map<String, String> mAttributes = new HashMap<String, String>();
|
|
||||||
|
|
||||||
public void setPrivacy(String privacy) {
|
|
||||||
mPrivacy = privacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPrivacy() {
|
|
||||||
return mPrivacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttribute(String name, String value) {
|
|
||||||
mAttributes.put(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAttribute(String name) {
|
|
||||||
mAttributes.remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getAllAttributes() {
|
|
||||||
return mAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-102
@@ -1,102 +0,0 @@
|
|||||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.client.GDataClient;
|
|
||||||
import com.google.wireless.gdata.client.GDataParserFactory;
|
|
||||||
import com.google.wireless.gdata.client.GDataServiceClient;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client to talk to Google Maps via GData.
|
|
||||||
*/
|
|
||||||
public class MapsClient extends GDataServiceClient {
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
public static final boolean LOG_COMMUNICATION = false;
|
|
||||||
|
|
||||||
private static final String MAPS_BASE_FEED_URL =
|
|
||||||
"http://maps.google.com/maps/feeds/";
|
|
||||||
private static final String MAPS_MAP_FEED_PATH = "maps/default/full";
|
|
||||||
private static final String MAPS_FEATURE_FEED_PATH_BEFORE_MAPID = "features/";
|
|
||||||
private static final String MAPS_FEATURE_FEED_PATH_AFTER_MAPID = "/full";
|
|
||||||
private static final String MAPS_VERSION_FEED_PATH_FORMAT =
|
|
||||||
"%smaps/%s/versions/%s/full/%s";
|
|
||||||
|
|
||||||
private static final String MAP_ENTRY_ID_BEFORE_USER_ID = "maps/feeds/maps/";
|
|
||||||
private static final String MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID = "/";
|
|
||||||
private static final String V2_ONLY_PARAM = "?v=2.0";
|
|
||||||
|
|
||||||
public MapsClient(GDataClient dataClient,
|
|
||||||
GDataParserFactory dataParserFactory) {
|
|
||||||
super(dataClient, dataParserFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServiceName() {
|
|
||||||
return MapsConstants.SERVICE_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String buildMapUrl(String mapId) {
|
|
||||||
return MapsConstants.MAPSHOP_BASE_URL + "?msa=0&msid=" + mapId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getMapsFeed() {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d("Maps Client", "Requesting map feed:");
|
|
||||||
}
|
|
||||||
return MAPS_BASE_FEED_URL + MAPS_MAP_FEED_PATH + V2_ONLY_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFeaturesFeed(String mapid) {
|
|
||||||
StringBuilder feed = new StringBuilder();
|
|
||||||
feed.append(MAPS_BASE_FEED_URL);
|
|
||||||
feed.append(MAPS_FEATURE_FEED_PATH_BEFORE_MAPID);
|
|
||||||
feed.append(mapid);
|
|
||||||
feed.append(MAPS_FEATURE_FEED_PATH_AFTER_MAPID);
|
|
||||||
feed.append(V2_ONLY_PARAM);
|
|
||||||
return feed.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getMapIdFromMapEntryId(String entryId) {
|
|
||||||
String userId = null;
|
|
||||||
String mapId = null;
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d("Maps GData Client", "Getting mapid from entry id: " + entryId);
|
|
||||||
}
|
|
||||||
int userIdStart =
|
|
||||||
entryId.indexOf(MAP_ENTRY_ID_BEFORE_USER_ID)
|
|
||||||
+ MAP_ENTRY_ID_BEFORE_USER_ID.length();
|
|
||||||
int userIdEnd =
|
|
||||||
entryId.indexOf(MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID, userIdStart);
|
|
||||||
if (userIdStart >= 0 && userIdEnd < entryId.length()
|
|
||||||
&& userIdStart <= userIdEnd) {
|
|
||||||
userId = entryId.substring(userIdStart, userIdEnd);
|
|
||||||
}
|
|
||||||
int mapIdStart =
|
|
||||||
entryId.indexOf(MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID, userIdEnd)
|
|
||||||
+ MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID.length();
|
|
||||||
if (mapIdStart >= 0 && mapIdStart < entryId.length()) {
|
|
||||||
mapId = entryId.substring(mapIdStart);
|
|
||||||
}
|
|
||||||
if (userId == null) {
|
|
||||||
userId = "";
|
|
||||||
}
|
|
||||||
if (mapId == null) {
|
|
||||||
mapId = "";
|
|
||||||
}
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d("Maps GData Client", "Got user id: " + userId);
|
|
||||||
Log.d("Maps GData Client", "Got map id: " + mapId);
|
|
||||||
}
|
|
||||||
return userId + "." + mapId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getVersionFeed(String versionUserId,
|
|
||||||
String versionClient, String currentVersion) {
|
|
||||||
return String.format(Locale.US, MAPS_VERSION_FEED_PATH_FORMAT, MAPS_BASE_FEED_URL,
|
|
||||||
versionUserId, versionClient, currentVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-16
@@ -1,16 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants for Google Maps.
|
|
||||||
*/
|
|
||||||
public class MapsConstants {
|
|
||||||
static final String MAPSHOP_BASE_URL =
|
|
||||||
"https://maps.google.com/maps/ms";
|
|
||||||
public static final String SERVICE_NAME = "local";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor to prevent instantiation.
|
|
||||||
*/
|
|
||||||
private MapsConstants() { }
|
|
||||||
}
|
|
||||||
-219
@@ -1,219 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MapsFeature contains all of the data associated with a feature in Google
|
|
||||||
* Maps, where a feature is a marker, line, or shape. Some of the data is stored
|
|
||||||
* in a {@link MapsFeatureMetadata} object so that it can be more efficiently
|
|
||||||
* transmitted to other activities.
|
|
||||||
*/
|
|
||||||
public class MapsFeature {
|
|
||||||
|
|
||||||
/** A marker feature displays an icon at a single point on the map. */
|
|
||||||
public static final int MARKER = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A line feature displays a line connecting a set of points on the map.
|
|
||||||
*/
|
|
||||||
public static final int LINE = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shape feature displays a border defined by connecting a set of points,
|
|
||||||
* including connecting the last to the first, and displays the area
|
|
||||||
* confined by this border.
|
|
||||||
*/
|
|
||||||
public static final int SHAPE = 2;
|
|
||||||
|
|
||||||
/** The local feature id for this feature, if needed. */
|
|
||||||
private String androidId;
|
|
||||||
|
|
||||||
// Points of this feature in order.
|
|
||||||
private final Vector<Location> points = new Vector<Location>();
|
|
||||||
|
|
||||||
/** The metadata of this feature in a format efficient for transmission. */
|
|
||||||
private MapsFeatureMetadata featureInfo = new MapsFeatureMetadata();
|
|
||||||
|
|
||||||
private final Random random = new Random();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a valid but empty feature. It will default to a
|
|
||||||
* {@link #MARKER} with a blue placemark with a dot as an icon at the
|
|
||||||
* location (0, 0).
|
|
||||||
*/
|
|
||||||
public MapsFeature() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new point to the end of this feature.
|
|
||||||
*
|
|
||||||
* @param location the new point to add
|
|
||||||
*/
|
|
||||||
public void addPoint(Location location) {
|
|
||||||
points.add(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a new local id for this feature based on the current time and
|
|
||||||
* a random number.
|
|
||||||
*/
|
|
||||||
public void generateAndroidId() {
|
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
int rand = random.nextInt(10000);
|
|
||||||
androidId = time + "." + rand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current local id for this feature if one is available.
|
|
||||||
*
|
|
||||||
* @return The local id for this feature
|
|
||||||
*/
|
|
||||||
public String getAndroidId() {
|
|
||||||
return androidId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current (html) description of this feature. The description
|
|
||||||
* is stored in the feature metadata.
|
|
||||||
*
|
|
||||||
* @return The description of this feature
|
|
||||||
*/
|
|
||||||
public String getDescription() {
|
|
||||||
return featureInfo.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the description of this feature. That description is stored in the
|
|
||||||
* feature metadata.
|
|
||||||
*
|
|
||||||
* @param description The new description of this feature
|
|
||||||
*/
|
|
||||||
public void setDescription(String description) {
|
|
||||||
featureInfo.setDescription(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the point at a given index.
|
|
||||||
*
|
|
||||||
* @param index the index
|
|
||||||
*/
|
|
||||||
public Location getPoint(int index) {
|
|
||||||
if (index >= points.size()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return points.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of points.
|
|
||||||
*/
|
|
||||||
public int getPointCount() {
|
|
||||||
return points.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the title of this feature. That title is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @return the current title of this feature
|
|
||||||
*/
|
|
||||||
public String getTitle() {
|
|
||||||
return featureInfo.getTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the type of this feature. That type is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @return One of {@link #MARKER}, {@link #LINE}, or {@link #SHAPE}
|
|
||||||
* identifying the type of this feature
|
|
||||||
*/
|
|
||||||
public int getType() {
|
|
||||||
return featureInfo.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current color of this feature as an ARGB color integer.
|
|
||||||
* That color is stored in the feature metadata.
|
|
||||||
*
|
|
||||||
* @return The ARGB color of this feature
|
|
||||||
*/
|
|
||||||
public int getColor() {
|
|
||||||
return featureInfo.getColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current line width of this feature. That line width is
|
|
||||||
* stored in the feature metadata.
|
|
||||||
*
|
|
||||||
* @return The line width of this feature
|
|
||||||
*/
|
|
||||||
public int getLineWidth() {
|
|
||||||
return featureInfo.getLineWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current fill color of this feature as an ARGB color
|
|
||||||
* integer. That color is stored in the feature metadata.
|
|
||||||
*
|
|
||||||
* @return The ARGB fill color of this feature
|
|
||||||
*/
|
|
||||||
public int getFillColor() {
|
|
||||||
return featureInfo.getFillColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the current icon url of this feature. That icon url is stored
|
|
||||||
* in the feature metadata.
|
|
||||||
*
|
|
||||||
* @return The icon url for this feature
|
|
||||||
*/
|
|
||||||
public String getIconUrl() {
|
|
||||||
return featureInfo.getIconUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title of this feature. That title is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @param title The new title of this feature
|
|
||||||
*/
|
|
||||||
public void setTitle(String title) {
|
|
||||||
featureInfo.setTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the type of this feature. That type is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @param type The new type of the feature. That type must be one of
|
|
||||||
* {@link #MARKER}, {@link #LINE}, or {@link #SHAPE}
|
|
||||||
*/
|
|
||||||
public void setType(int type) {
|
|
||||||
featureInfo.setType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the ARGB color of this feature. That color is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @param color The new ARGB color of this feature
|
|
||||||
*/
|
|
||||||
public void setColor(int color) {
|
|
||||||
featureInfo.setColor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the icon url of this feature. That icon url is stored in the feature
|
|
||||||
* metadata.
|
|
||||||
*
|
|
||||||
* @param url The new icon url of the feature
|
|
||||||
*/
|
|
||||||
public void setIconUrl(String url) {
|
|
||||||
featureInfo.setIconUrl(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-88
@@ -1,88 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata about a maps feature.
|
|
||||||
*/
|
|
||||||
class MapsFeatureMetadata {
|
|
||||||
|
|
||||||
private static final String BLUE_DOT_URL =
|
|
||||||
"http://maps.google.com/mapfiles/ms/micons/blue-dot.png";
|
|
||||||
private static final int DEFAULT_COLOR = 0x800000FF;
|
|
||||||
private static final int DEFAULT_FILL_COLOR = 0xC00000FF;
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
private String description;
|
|
||||||
private int type;
|
|
||||||
private int color;
|
|
||||||
private int lineWidth;
|
|
||||||
private int fillColor;
|
|
||||||
private String iconUrl;
|
|
||||||
|
|
||||||
public MapsFeatureMetadata() {
|
|
||||||
title = "";
|
|
||||||
description = "";
|
|
||||||
type = MapsFeature.MARKER;
|
|
||||||
color = DEFAULT_COLOR;
|
|
||||||
lineWidth = 5;
|
|
||||||
fillColor = DEFAULT_FILL_COLOR;
|
|
||||||
iconUrl = BLUE_DOT_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(int type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColor() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int color) {
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLineWidth() {
|
|
||||||
return lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLineWidth(int width) {
|
|
||||||
lineWidth = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFillColor() {
|
|
||||||
return fillColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFillColor(int color) {
|
|
||||||
fillColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIconUrl() {
|
|
||||||
return iconUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIconUrl(String url) {
|
|
||||||
iconUrl = url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-178
@@ -1,178 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.data.Entry;
|
|
||||||
import com.google.wireless.gdata.data.StringUtils;
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converter from GData objects to Maps objects.
|
|
||||||
*/
|
|
||||||
public class MapsGDataConverter {
|
|
||||||
|
|
||||||
private final XmlSerializer xmlSerializer;
|
|
||||||
|
|
||||||
public MapsGDataConverter() throws XmlPullParserException {
|
|
||||||
xmlSerializer = XmlPullParserFactory.newInstance().newSerializer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MapsMapMetadata getMapMetadataForEntry(
|
|
||||||
MapFeatureEntry entry) {
|
|
||||||
MapsMapMetadata metadata = new MapsMapMetadata();
|
|
||||||
if ("public".equals(entry.getPrivacy())) {
|
|
||||||
metadata.setSearchable(true);
|
|
||||||
} else {
|
|
||||||
metadata.setSearchable(false);
|
|
||||||
}
|
|
||||||
metadata.setTitle(entry.getTitle());
|
|
||||||
metadata.setDescription(entry.getSummary());
|
|
||||||
|
|
||||||
String editUri = entry.getEditUri();
|
|
||||||
if (editUri != null) {
|
|
||||||
metadata.setGDataEditUri(editUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getMapidForEntry(Entry entry) {
|
|
||||||
return MapsClient.getMapIdFromMapEntryId(entry.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Entry getMapEntryForMetadata(MapsMapMetadata metadata) {
|
|
||||||
MapFeatureEntry entry = new MapFeatureEntry();
|
|
||||||
entry.setEditUri(metadata.getGDataEditUri());
|
|
||||||
entry.setTitle(metadata.getTitle());
|
|
||||||
entry.setSummary(metadata.getDescription());
|
|
||||||
entry.setPrivacy(metadata.getSearchable() ? "public" : "unlisted");
|
|
||||||
entry.setAuthor("android");
|
|
||||||
entry.setEmail("nobody@google.com");
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MapFeatureEntry getEntryForFeature(MapsFeature feature) {
|
|
||||||
MapFeatureEntry entry = new MapFeatureEntry();
|
|
||||||
entry.setTitle(feature.getTitle());
|
|
||||||
entry.setAuthor("android");
|
|
||||||
entry.setEmail("nobody@google.com");
|
|
||||||
entry.setCategoryScheme("http://schemas.google.com/g/2005#kind");
|
|
||||||
entry.setCategory("http://schemas.google.com/g/2008#mapfeature");
|
|
||||||
entry.setEditUri("");
|
|
||||||
if (!StringUtils.isEmpty(feature.getAndroidId())) {
|
|
||||||
entry.setAttribute("_androidId", feature.getAndroidId());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
xmlSerializer.setOutput(writer);
|
|
||||||
xmlSerializer.startTag(null, "Placemark");
|
|
||||||
xmlSerializer.attribute(null, "xmlns", "http://earth.google.com/kml/2.2");
|
|
||||||
xmlSerializer.startTag(null, "Style");
|
|
||||||
if (feature.getType() == MapsFeature.MARKER) {
|
|
||||||
xmlSerializer.startTag(null, "IconStyle");
|
|
||||||
xmlSerializer.startTag(null, "Icon");
|
|
||||||
xmlSerializer.startTag(null, "href");
|
|
||||||
xmlSerializer.text(feature.getIconUrl());
|
|
||||||
xmlSerializer.endTag(null, "href");
|
|
||||||
xmlSerializer.endTag(null, "Icon");
|
|
||||||
xmlSerializer.endTag(null, "IconStyle");
|
|
||||||
} else {
|
|
||||||
xmlSerializer.startTag(null, "LineStyle");
|
|
||||||
xmlSerializer.startTag(null, "color");
|
|
||||||
int color = feature.getColor();
|
|
||||||
// Reverse the color because KML is ABGR and Android is ARGB
|
|
||||||
xmlSerializer.text(Integer.toHexString(
|
|
||||||
Color.argb(Color.alpha(color), Color.blue(color),
|
|
||||||
Color.green(color), Color.red(color))));
|
|
||||||
xmlSerializer.endTag(null, "color");
|
|
||||||
xmlSerializer.startTag(null, "width");
|
|
||||||
xmlSerializer.text(Integer.toString(feature.getLineWidth()));
|
|
||||||
xmlSerializer.endTag(null, "width");
|
|
||||||
xmlSerializer.endTag(null, "LineStyle");
|
|
||||||
|
|
||||||
if (feature.getType() == MapsFeature.SHAPE) {
|
|
||||||
xmlSerializer.startTag(null, "PolyStyle");
|
|
||||||
xmlSerializer.startTag(null, "color");
|
|
||||||
int fcolor = feature.getFillColor();
|
|
||||||
// Reverse the color because KML is ABGR and Android is ARGB
|
|
||||||
xmlSerializer.text(Integer.toHexString(Color.argb(Color.alpha(fcolor),
|
|
||||||
Color.blue(fcolor), Color.green(fcolor), Color.red(fcolor))));
|
|
||||||
xmlSerializer.endTag(null, "color");
|
|
||||||
xmlSerializer.startTag(null, "fill");
|
|
||||||
xmlSerializer.text("1");
|
|
||||||
xmlSerializer.endTag(null, "fill");
|
|
||||||
xmlSerializer.startTag(null, "outline");
|
|
||||||
xmlSerializer.text("1");
|
|
||||||
xmlSerializer.endTag(null, "outline");
|
|
||||||
xmlSerializer.endTag(null, "PolyStyle");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlSerializer.endTag(null, "Style");
|
|
||||||
xmlSerializer.startTag(null, "name");
|
|
||||||
xmlSerializer.text(feature.getTitle());
|
|
||||||
xmlSerializer.endTag(null, "name");
|
|
||||||
xmlSerializer.startTag(null, "description");
|
|
||||||
xmlSerializer.cdsect(feature.getDescription());
|
|
||||||
xmlSerializer.endTag(null, "description");
|
|
||||||
StringBuilder pointBuilder = new StringBuilder();
|
|
||||||
for (int i = 0; i < feature.getPointCount(); ++i) {
|
|
||||||
if (i > 0) {
|
|
||||||
pointBuilder.append('\n');
|
|
||||||
}
|
|
||||||
pointBuilder.append(feature.getPoint(i).getLongitude());
|
|
||||||
pointBuilder.append(',');
|
|
||||||
pointBuilder.append(feature.getPoint(i).getLatitude());
|
|
||||||
pointBuilder.append(",0.000000");
|
|
||||||
}
|
|
||||||
String pointString = pointBuilder.toString();
|
|
||||||
if (feature.getType() == MapsFeature.MARKER) {
|
|
||||||
xmlSerializer.startTag(null, "Point");
|
|
||||||
xmlSerializer.startTag(null, "coordinates");
|
|
||||||
xmlSerializer.text(pointString);
|
|
||||||
xmlSerializer.endTag(null, "coordinates");
|
|
||||||
xmlSerializer.endTag(null, "Point");
|
|
||||||
} else if (feature.getType() == MapsFeature.LINE) {
|
|
||||||
xmlSerializer.startTag(null, "LineString");
|
|
||||||
xmlSerializer.startTag(null, "tessellate");
|
|
||||||
xmlSerializer.text("1");
|
|
||||||
xmlSerializer.endTag(null, "tessellate");
|
|
||||||
xmlSerializer.startTag(null, "coordinates");
|
|
||||||
xmlSerializer.text(pointString);
|
|
||||||
xmlSerializer.endTag(null, "coordinates");
|
|
||||||
xmlSerializer.endTag(null, "LineString");
|
|
||||||
} else {
|
|
||||||
xmlSerializer.startTag(null, "Polygon");
|
|
||||||
xmlSerializer.startTag(null, "outerBoundaryIs");
|
|
||||||
xmlSerializer.startTag(null, "LinearRing");
|
|
||||||
xmlSerializer.startTag(null, "tessellate");
|
|
||||||
xmlSerializer.text("1");
|
|
||||||
xmlSerializer.endTag(null, "tessellate");
|
|
||||||
xmlSerializer.startTag(null, "coordinates");
|
|
||||||
xmlSerializer.text(pointString + "\n"
|
|
||||||
+ Double.toString(feature.getPoint(0).getLongitude())
|
|
||||||
+ ","
|
|
||||||
+ Double.toString(feature.getPoint(0).getLatitude())
|
|
||||||
+ ",0.000000");
|
|
||||||
xmlSerializer.endTag(null, "coordinates");
|
|
||||||
xmlSerializer.endTag(null, "LinearRing");
|
|
||||||
xmlSerializer.endTag(null, "outerBoundaryIs");
|
|
||||||
xmlSerializer.endTag(null, "Polygon");
|
|
||||||
}
|
|
||||||
xmlSerializer.endTag(null, "Placemark");
|
|
||||||
xmlSerializer.flush();
|
|
||||||
entry.setContent(writer.toString());
|
|
||||||
Log.d("My Google Maps", "Edit URI: " + entry.getEditUri());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata about a Google Maps map.
|
|
||||||
*/
|
|
||||||
public class MapsMapMetadata {
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
private String description;
|
|
||||||
private String gdataEditUri;
|
|
||||||
private boolean searchable;
|
|
||||||
|
|
||||||
public MapsMapMetadata() {
|
|
||||||
title = "";
|
|
||||||
description = "";
|
|
||||||
gdataEditUri = "";
|
|
||||||
searchable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getSearchable() {
|
|
||||||
return searchable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSearchable(boolean searchable) {
|
|
||||||
this.searchable = searchable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGDataEditUri() {
|
|
||||||
return gdataEditUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGDataEditUri(String editUri) {
|
|
||||||
this.gdataEditUri = editUri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-163
@@ -1,163 +0,0 @@
|
|||||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.data.Entry;
|
|
||||||
import com.google.wireless.gdata.data.Feed;
|
|
||||||
import com.google.wireless.gdata.data.XmlUtils;
|
|
||||||
import com.google.wireless.gdata.parser.ParseException;
|
|
||||||
import com.google.wireless.gdata.parser.xml.XmlGDataParser;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser for XML gdata maps data.
|
|
||||||
*/
|
|
||||||
class XmlMapsGDataParser extends XmlGDataParser {
|
|
||||||
|
|
||||||
public XmlMapsGDataParser(InputStream is, XmlPullParser xpp)
|
|
||||||
throws ParseException {
|
|
||||||
super(is, xpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Feed createFeed() {
|
|
||||||
return new Feed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Entry createEntry() {
|
|
||||||
return new MapFeatureEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleExtraElementInFeed(Feed feed) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleExtraLinkInEntry(
|
|
||||||
String rel, String type, String href, Entry entry)
|
|
||||||
throws XmlPullParserException, IOException {
|
|
||||||
if (!(entry instanceof MapFeatureEntry)) {
|
|
||||||
throw new IllegalArgumentException("Expected MapFeatureEntry!");
|
|
||||||
}
|
|
||||||
if (rel.endsWith("#view")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
super.handleExtraLinkInEntry(rel, type, href, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the current entry in the XML document. Assumes that the parser is
|
|
||||||
* currently pointing just after an <entry>.
|
|
||||||
*
|
|
||||||
* @param plainEntry The entry that will be filled.
|
|
||||||
* @throws XmlPullParserException Thrown if the XML cannot be parsed.
|
|
||||||
* @throws IOException Thrown if the underlying inputstream cannot be read.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void handleEntry(Entry plainEntry)
|
|
||||||
throws XmlPullParserException, IOException, ParseException {
|
|
||||||
XmlPullParser parser = getParser();
|
|
||||||
if (!(plainEntry instanceof MapFeatureEntry)) {
|
|
||||||
throw new IllegalArgumentException("Expected MapFeatureEntry!");
|
|
||||||
}
|
|
||||||
MapFeatureEntry entry = (MapFeatureEntry) plainEntry;
|
|
||||||
|
|
||||||
int eventType = parser.getEventType();
|
|
||||||
entry.setPrivacy("public");
|
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
|
||||||
switch (eventType) {
|
|
||||||
case XmlPullParser.START_TAG:
|
|
||||||
String name = parser.getName();
|
|
||||||
if ("entry".equals(name)) {
|
|
||||||
// stop parsing here.
|
|
||||||
return;
|
|
||||||
} else if ("id".equals(name)) {
|
|
||||||
entry.setId(XmlUtils.extractChildText(parser));
|
|
||||||
} else if ("title".equals(name)) {
|
|
||||||
entry.setTitle(XmlUtils.extractChildText(parser));
|
|
||||||
} else if ("link".equals(name)) {
|
|
||||||
String rel = parser.getAttributeValue(null /* ns */, "rel");
|
|
||||||
String type = parser.getAttributeValue(null /* ns */, "type");
|
|
||||||
String href = parser.getAttributeValue(null /* ns */, "href");
|
|
||||||
if ("edit".equals(rel)) {
|
|
||||||
entry.setEditUri(href);
|
|
||||||
} else if ("alternate".equals(rel) && "text/html".equals(type)) {
|
|
||||||
entry.setHtmlUri(href);
|
|
||||||
} else {
|
|
||||||
handleExtraLinkInEntry(rel, type, href, entry);
|
|
||||||
}
|
|
||||||
} else if ("summary".equals(name)) {
|
|
||||||
entry.setSummary(XmlUtils.extractChildText(parser));
|
|
||||||
} else if ("content".equals(name)) {
|
|
||||||
StringBuilder contentBuilder = new StringBuilder();
|
|
||||||
int parentDepth = parser.getDepth();
|
|
||||||
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
|
|
||||||
int etype = parser.next();
|
|
||||||
switch (etype) {
|
|
||||||
case XmlPullParser.START_TAG:
|
|
||||||
contentBuilder.append('<');
|
|
||||||
contentBuilder.append(parser.getName());
|
|
||||||
contentBuilder.append('>');
|
|
||||||
break;
|
|
||||||
case XmlPullParser.TEXT:
|
|
||||||
contentBuilder.append("<![CDATA[");
|
|
||||||
contentBuilder.append(parser.getText());
|
|
||||||
contentBuilder.append("]]>");
|
|
||||||
break;
|
|
||||||
case XmlPullParser.END_TAG:
|
|
||||||
if (parser.getDepth() > parentDepth) {
|
|
||||||
contentBuilder.append("</");
|
|
||||||
contentBuilder.append(parser.getName());
|
|
||||||
contentBuilder.append('>');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (etype == XmlPullParser.END_TAG
|
|
||||||
&& parser.getDepth() == parentDepth) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.setContent(contentBuilder.toString());
|
|
||||||
} else if ("category".equals(name)) {
|
|
||||||
String category = parser.getAttributeValue(null /* ns */, "term");
|
|
||||||
if (category != null && category.length() > 0) {
|
|
||||||
entry.setCategory(category);
|
|
||||||
}
|
|
||||||
String categoryScheme =
|
|
||||||
parser.getAttributeValue(null /* ns */, "scheme");
|
|
||||||
if (categoryScheme != null && category.length() > 0) {
|
|
||||||
entry.setCategoryScheme(categoryScheme);
|
|
||||||
}
|
|
||||||
} else if ("published".equals(name)) {
|
|
||||||
entry.setPublicationDate(XmlUtils.extractChildText(parser));
|
|
||||||
} else if ("updated".equals(name)) {
|
|
||||||
entry.setUpdateDate(XmlUtils.extractChildText(parser));
|
|
||||||
} else if ("deleted".equals(name)) {
|
|
||||||
entry.setDeleted(true);
|
|
||||||
} else if ("draft".equals(name)) {
|
|
||||||
String draft = XmlUtils.extractChildText(parser);
|
|
||||||
entry.setPrivacy("yes".equals(draft) ? "unlisted" : "public");
|
|
||||||
} else if ("customProperty".equals(name)) {
|
|
||||||
String attrName = parser.getAttributeValue(null, "name");
|
|
||||||
String attrValue = XmlUtils.extractChildText(parser);
|
|
||||||
entry.setAttribute(attrName, attrValue);
|
|
||||||
} else if ("deleted".equals(name)) {
|
|
||||||
entry.setDeleted(true);
|
|
||||||
} else {
|
|
||||||
handleExtraElementInEntry(entry);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
eventType = parser.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-94
@@ -1,94 +0,0 @@
|
|||||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.wireless.gdata.client.GDataParserFactory;
|
|
||||||
import com.google.wireless.gdata.data.Entry;
|
|
||||||
import com.google.wireless.gdata.parser.GDataParser;
|
|
||||||
import com.google.wireless.gdata.parser.ParseException;
|
|
||||||
import com.google.wireless.gdata.parser.xml.XmlGDataParser;
|
|
||||||
import com.google.wireless.gdata.parser.xml.XmlParserFactory;
|
|
||||||
import com.google.wireless.gdata.serializer.GDataSerializer;
|
|
||||||
import com.google.wireless.gdata.serializer.xml.XmlEntryGDataSerializer;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory of Xml parsers for gdata maps data.
|
|
||||||
*/
|
|
||||||
public class XmlMapsGDataParserFactory implements GDataParserFactory {
|
|
||||||
private XmlParserFactory xmlFactory;
|
|
||||||
|
|
||||||
public XmlMapsGDataParserFactory(XmlParserFactory xmlFactory) {
|
|
||||||
this.xmlFactory = xmlFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GDataParser createParser(InputStream is) throws ParseException {
|
|
||||||
is = maybeLogCommunication(is);
|
|
||||||
try {
|
|
||||||
return new XmlGDataParser(is, xmlFactory.createParser());
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
@Override
|
|
||||||
public GDataParser createParser(Class cls, InputStream is)
|
|
||||||
throws ParseException {
|
|
||||||
is = maybeLogCommunication(is);
|
|
||||||
try {
|
|
||||||
return createParserForClass(cls, is);
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream maybeLogCommunication(InputStream is)
|
|
||||||
throws ParseException {
|
|
||||||
if (MapsClient.LOG_COMMUNICATION) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
byte[] buffer = new byte[2048];
|
|
||||||
try {
|
|
||||||
for (int n = is.read(buffer); n >= 0; n = is.read(buffer)) {
|
|
||||||
String part = new String(buffer, 0, n);
|
|
||||||
builder.append(part);
|
|
||||||
Log.d("Response part", part);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ParseException("Could not read stream", e);
|
|
||||||
}
|
|
||||||
String whole = builder.toString();
|
|
||||||
Log.d("Response", whole);
|
|
||||||
is = new ByteArrayInputStream(whole.getBytes());
|
|
||||||
}
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GDataParser createParserForClass(
|
|
||||||
Class<? extends Entry> cls, InputStream is)
|
|
||||||
throws ParseException, XmlPullParserException {
|
|
||||||
if (cls == MapFeatureEntry.class) {
|
|
||||||
return new XmlMapsGDataParser(is, xmlFactory.createParser());
|
|
||||||
} else {
|
|
||||||
return new XmlGDataParser(is, xmlFactory.createParser());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GDataSerializer createSerializer(Entry en) {
|
|
||||||
if (en instanceof MapFeatureEntry) {
|
|
||||||
return new XmlMapsGDataSerializer(xmlFactory, (MapFeatureEntry) en);
|
|
||||||
} else {
|
|
||||||
return new XmlEntryGDataSerializer(xmlFactory, en);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-262
@@ -1,262 +0,0 @@
|
|||||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
package com.google.android.apps.mytracks.io.gdata.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
|
||||||
import com.google.wireless.gdata.data.StringUtils;
|
|
||||||
import com.google.wireless.gdata.parser.ParseException;
|
|
||||||
import com.google.wireless.gdata.parser.xml.XmlGDataParser;
|
|
||||||
import com.google.wireless.gdata.parser.xml.XmlParserFactory;
|
|
||||||
import com.google.wireless.gdata.serializer.xml.XmlEntryGDataSerializer;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializer of maps data for GData.
|
|
||||||
*/
|
|
||||||
class XmlMapsGDataSerializer extends XmlEntryGDataSerializer {
|
|
||||||
|
|
||||||
private static final String APP_NAMESPACE = "http://www.w3.org/2007/app";
|
|
||||||
|
|
||||||
private MapFeatureEntry entry;
|
|
||||||
private XmlParserFactory factory;
|
|
||||||
private OutputStream stream;
|
|
||||||
|
|
||||||
public XmlMapsGDataSerializer(XmlParserFactory factory, MapFeatureEntry entry) {
|
|
||||||
super(factory, entry);
|
|
||||||
|
|
||||||
this.factory = factory;
|
|
||||||
this.entry = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serialize(OutputStream out, int format)
|
|
||||||
throws IOException, ParseException {
|
|
||||||
XmlSerializer serializer = null;
|
|
||||||
try {
|
|
||||||
serializer = factory.createSerializer();
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
throw new ParseException("Unable to create XmlSerializer.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream printStream;
|
|
||||||
|
|
||||||
if (MapsClient.LOG_COMMUNICATION) {
|
|
||||||
printStream = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
serializer.setOutput(printStream, "UTF-8");
|
|
||||||
} else {
|
|
||||||
serializer.setOutput(out, "UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
serializer.startDocument("UTF-8", Boolean.FALSE);
|
|
||||||
|
|
||||||
declareEntryNamespaces(serializer);
|
|
||||||
serializer.startTag(XmlGDataParser.NAMESPACE_ATOM_URI, "entry");
|
|
||||||
|
|
||||||
if (MapsClient.LOG_COMMUNICATION) {
|
|
||||||
stream = printStream;
|
|
||||||
} else {
|
|
||||||
stream = out;
|
|
||||||
}
|
|
||||||
serializeEntryContents(serializer, format);
|
|
||||||
|
|
||||||
serializer.endTag(XmlGDataParser.NAMESPACE_ATOM_URI, "entry");
|
|
||||||
serializer.endDocument();
|
|
||||||
serializer.flush();
|
|
||||||
|
|
||||||
if (MapsClient.LOG_COMMUNICATION) {
|
|
||||||
Log.d("Request", printStream.toString());
|
|
||||||
out.write(printStream.toByteArray());
|
|
||||||
stream = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void declareEntryNamespaces(XmlSerializer serializer)
|
|
||||||
throws IOException {
|
|
||||||
serializer.setPrefix(
|
|
||||||
"" /* default ns */, XmlGDataParser.NAMESPACE_ATOM_URI);
|
|
||||||
serializer.setPrefix(
|
|
||||||
XmlGDataParser.NAMESPACE_GD, XmlGDataParser.NAMESPACE_GD_URI);
|
|
||||||
declareExtraEntryNamespaces(serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void serializeEntryContents(XmlSerializer serializer,
|
|
||||||
int format) throws IOException {
|
|
||||||
if (format != FORMAT_CREATE) {
|
|
||||||
serializeId(serializer, entry.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeTitle(serializer, entry.getTitle());
|
|
||||||
|
|
||||||
if (format != FORMAT_CREATE) {
|
|
||||||
serializeLink(serializer,
|
|
||||||
"edit" /* rel */, entry.getEditUri(), null /* type */);
|
|
||||||
serializeLink(serializer,
|
|
||||||
"alternate" /* rel */, entry.getHtmlUri(), "text/html" /* type */);
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeSummary(serializer, entry.getSummary());
|
|
||||||
serializeContent(serializer, entry.getContent());
|
|
||||||
serializeAuthor(serializer, entry.getAuthor(), entry.getEmail());
|
|
||||||
serializeCategory(serializer,
|
|
||||||
entry.getCategory(), entry.getCategoryScheme());
|
|
||||||
|
|
||||||
if (format == FORMAT_FULL) {
|
|
||||||
serializePublicationDate(serializer, entry.getPublicationDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format != FORMAT_CREATE) {
|
|
||||||
serializeUpdateDate(serializer, entry.getUpdateDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeExtraEntryContents(serializer, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeId(XmlSerializer serializer, String id)
|
|
||||||
throws IOException {
|
|
||||||
if (StringUtils.isEmpty(id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "id");
|
|
||||||
serializer.text(id);
|
|
||||||
serializer.endTag(null /* ns */, "id");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeTitle(XmlSerializer serializer, String title)
|
|
||||||
throws IOException {
|
|
||||||
if (StringUtils.isEmpty(title)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "title");
|
|
||||||
serializer.text(title);
|
|
||||||
serializer.endTag(null /* ns */, "title");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void serializeLink(XmlSerializer serializer, String rel,
|
|
||||||
String href, String type) throws IOException {
|
|
||||||
if (StringUtils.isEmpty(href)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "link");
|
|
||||||
serializer.attribute(null /* ns */, "rel", rel);
|
|
||||||
serializer.attribute(null /* ns */, "href", href);
|
|
||||||
if (!StringUtils.isEmpty(type)) {
|
|
||||||
serializer.attribute(null /* ns */, "type", type);
|
|
||||||
}
|
|
||||||
serializer.endTag(null /* ns */, "link");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeSummary(XmlSerializer serializer, String summary)
|
|
||||||
throws IOException {
|
|
||||||
if (StringUtils.isEmpty(summary)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "summary");
|
|
||||||
serializer.text(summary);
|
|
||||||
serializer.endTag(null /* ns */, "summary");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void serializeContent(XmlSerializer serializer, String content)
|
|
||||||
throws IOException {
|
|
||||||
if (content == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "content");
|
|
||||||
if (content.contains("</Placemark>")) {
|
|
||||||
serializer.attribute(null /* ns */, "type", SyncUtils.KML_MIME_TYPE);
|
|
||||||
serializer.flush();
|
|
||||||
stream.write(content.getBytes());
|
|
||||||
} else {
|
|
||||||
serializer.text(content);
|
|
||||||
}
|
|
||||||
serializer.endTag(null /* ns */, "content");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeAuthor(XmlSerializer serializer, String author,
|
|
||||||
String email) throws IOException {
|
|
||||||
if (StringUtils.isEmpty(author) || StringUtils.isEmpty(email)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "author");
|
|
||||||
serializer.startTag(null /* ns */, "name");
|
|
||||||
serializer.text(author);
|
|
||||||
serializer.endTag(null /* ns */, "name");
|
|
||||||
serializer.startTag(null /* ns */, "email");
|
|
||||||
serializer.text(email);
|
|
||||||
serializer.endTag(null /* ns */, "email");
|
|
||||||
serializer.endTag(null /* ns */, "author");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeCategory(XmlSerializer serializer,
|
|
||||||
String category, String categoryScheme) throws IOException {
|
|
||||||
if (StringUtils.isEmpty(category) && StringUtils.isEmpty(categoryScheme)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "category");
|
|
||||||
if (!StringUtils.isEmpty(category)) {
|
|
||||||
serializer.attribute(null /* ns */, "term", category);
|
|
||||||
}
|
|
||||||
if (!StringUtils.isEmpty(categoryScheme)) {
|
|
||||||
serializer.attribute(null /* ns */, "scheme", categoryScheme);
|
|
||||||
}
|
|
||||||
serializer.endTag(null /* ns */, "category");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializePublicationDate(XmlSerializer serializer,
|
|
||||||
String publicationDate) throws IOException {
|
|
||||||
if (StringUtils.isEmpty(publicationDate)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "published");
|
|
||||||
serializer.text(publicationDate);
|
|
||||||
serializer.endTag(null /* ns */, "published");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void serializeUpdateDate(XmlSerializer serializer,
|
|
||||||
String updateDate) throws IOException {
|
|
||||||
if (StringUtils.isEmpty(updateDate)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
serializer.startTag(null /* ns */, "updated");
|
|
||||||
serializer.text(updateDate);
|
|
||||||
serializer.endTag(null /* ns */, "updated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void serializeExtraEntryContents(XmlSerializer serializer,
|
|
||||||
int format) throws IOException {
|
|
||||||
Map<String, String> attrs = entry.getAllAttributes();
|
|
||||||
for (Map.Entry<String, String> attr : attrs.entrySet()) {
|
|
||||||
serializer.startTag("http://schemas.google.com/g/2005", "customProperty");
|
|
||||||
serializer.attribute(null, "name", attr.getKey());
|
|
||||||
serializer.text(attr.getValue());
|
|
||||||
serializer.endTag("http://schemas.google.com/g/2005", "customProperty");
|
|
||||||
}
|
|
||||||
String privacy = entry.getPrivacy();
|
|
||||||
if (!StringUtils.isEmpty(privacy)) {
|
|
||||||
serializer.setPrefix("app", APP_NAMESPACE);
|
|
||||||
if ("public".equals(privacy)) {
|
|
||||||
serializer.startTag(APP_NAMESPACE, "control");
|
|
||||||
serializer.startTag(APP_NAMESPACE, "draft");
|
|
||||||
serializer.text("no");
|
|
||||||
serializer.endTag(APP_NAMESPACE, "draft");
|
|
||||||
serializer.endTag(APP_NAMESPACE, "control");
|
|
||||||
}
|
|
||||||
if ("unlisted".equals(privacy)) {
|
|
||||||
serializer.startTag(APP_NAMESPACE, "control");
|
|
||||||
serializer.startTag(APP_NAMESPACE, "draft");
|
|
||||||
serializer.text("yes");
|
|
||||||
serializer.endTag(APP_NAMESPACE, "draft");
|
|
||||||
serializer.endTag(APP_NAMESPACE, "control");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An activity to send a track to Google Maps.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendMapsActivity extends AbstractSendActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractSendAsyncTask createAsyncTask() {
|
|
||||||
return new SendMapsAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getServiceName() {
|
|
||||||
return getString(R.string.export_google_maps);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void startNextActivity(boolean success, boolean isCancel) {
|
|
||||||
sendRequest.setMapsSuccess(success);
|
|
||||||
Class<?> next = getNextClass(sendRequest, isCancel);
|
|
||||||
Intent intent = IntentUtils.newIntent(this, next)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
Class<?> getNextClass(SendRequest request, boolean isCancel) {
|
|
||||||
if (isCancel) {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
} else {
|
|
||||||
if (request.isSendFusionTables()) {
|
|
||||||
return SendFusionTablesActivity.class;
|
|
||||||
} else if (request.isSendSpreadsheets()) {
|
|
||||||
return SendSpreadsheetsActivity.class;
|
|
||||||
} else {
|
|
||||||
return UploadResultActivity.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-505
@@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
|
||||||
import com.google.android.apps.mytracks.content.DescriptionGenerator;
|
|
||||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsClient;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.XmlMapsGDataParserFactory;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.stats.TripStatisticsUpdater;
|
|
||||||
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
|
|
||||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.common.gdata.AndroidXmlParserFactory;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
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.ParseException;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.accounts.AuthenticatorException;
|
|
||||||
import android.accounts.OperationCanceledException;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AsyncTask to send a track to Google Maps.
|
|
||||||
* <p>
|
|
||||||
* IMPORTANT: While this code is Apache-licensed, please notice that usage of
|
|
||||||
* the Google Maps servers through this API is only allowed for the My Tracks
|
|
||||||
* application. Other applications looking to upload maps data should look into
|
|
||||||
* using the Google Fusion Tables API.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendMapsAsyncTask extends AbstractSendAsyncTask {
|
|
||||||
private static final String
|
|
||||||
START_ICON_URL = "http://maps.google.com/mapfiles/ms/micons/green-dot.png";
|
|
||||||
private static final String
|
|
||||||
END_ICON_URL = "http://maps.google.com/mapfiles/ms/micons/red-dot.png";
|
|
||||||
private static final int MAX_POINTS_PER_UPLOAD = 500;
|
|
||||||
|
|
||||||
private static final int PROGRESS_FETCH_MAP_ID = 5;
|
|
||||||
@VisibleForTesting
|
|
||||||
static final int PROGRESS_UPLOAD_DATA_MIN = 10;
|
|
||||||
@VisibleForTesting
|
|
||||||
static final int PROGRESS_UPLOAD_DATA_MAX = 90;
|
|
||||||
private static final int PROGRESS_UPLOAD_WAYPOINTS = 95;
|
|
||||||
private static final int PROGRESS_COMPLETE = 100;
|
|
||||||
|
|
||||||
private static final String TAG = SendMapsAsyncTask.class.getSimpleName();
|
|
||||||
|
|
||||||
private final long trackId;
|
|
||||||
private final Account account;
|
|
||||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
|
||||||
private final Context context;
|
|
||||||
private final GDataClient gDataClient;
|
|
||||||
private final MapsClient mapsClient;
|
|
||||||
|
|
||||||
// The following variables are for per upload states
|
|
||||||
private MapsGDataConverter mapsGDataConverter;
|
|
||||||
private String authToken;
|
|
||||||
private String mapId;
|
|
||||||
int currentSegment;
|
|
||||||
|
|
||||||
public SendMapsAsyncTask(SendMapsActivity activity, long trackId, Account account) {
|
|
||||||
this(activity, trackId, account, MyTracksProviderUtils.Factory.get(
|
|
||||||
activity.getApplicationContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor is created for test.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
public SendMapsAsyncTask(SendMapsActivity activity, long trackId, Account account,
|
|
||||||
MyTracksProviderUtils myTracksProviderUtils) {
|
|
||||||
super(activity);
|
|
||||||
this.trackId = trackId;
|
|
||||||
this.account = account;
|
|
||||||
this.myTracksProviderUtils = myTracksProviderUtils;
|
|
||||||
context = activity.getApplicationContext();
|
|
||||||
|
|
||||||
gDataClient = GDataClientFactory.getGDataClient(context);
|
|
||||||
mapsClient = new MapsClient(
|
|
||||||
gDataClient, new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void closeConnection() {
|
|
||||||
if (gDataClient != null) {
|
|
||||||
gDataClient.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performTask() {
|
|
||||||
// Reset the per upload states
|
|
||||||
mapsGDataConverter = null;
|
|
||||||
authToken = null;
|
|
||||||
mapId = null;
|
|
||||||
currentSegment = 1;
|
|
||||||
|
|
||||||
// Create a maps gdata converter
|
|
||||||
try {
|
|
||||||
mapsGDataConverter = new MapsGDataConverter();
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
Log.d(TAG, "Unable to create a maps gdata converter", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get auth token
|
|
||||||
try {
|
|
||||||
authToken = AccountManager.get(context)
|
|
||||||
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false);
|
|
||||||
} catch (OperationCanceledException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
return retryTask();
|
|
||||||
} catch (AuthenticatorException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
return retryTask();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to get auth token", e);
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the track
|
|
||||||
Track track = myTracksProviderUtils.getTrack(trackId);
|
|
||||||
if (track == null) {
|
|
||||||
Log.d(TAG, "No track for " + trackId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the mapId, create a new map if necessary
|
|
||||||
publishProgress(PROGRESS_FETCH_MAP_ID);
|
|
||||||
if (!fetchSendMapId(track)) {
|
|
||||||
Log.d("TAG", "Unable to upload all track points");
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload all the track points plus the start and end markers
|
|
||||||
publishProgress(PROGRESS_UPLOAD_DATA_MIN);
|
|
||||||
if (!uploadAllTrackPoints(track)) {
|
|
||||||
Log.d("TAG", "Unable to upload all track points");
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload all the waypoints
|
|
||||||
publishProgress(PROGRESS_UPLOAD_WAYPOINTS);
|
|
||||||
if (!uploadWaypoints()) {
|
|
||||||
Log.d("TAG", "Unable to upload waypoints");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_COMPLETE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidateToken() {
|
|
||||||
AccountManager.get(context).invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the {@link SendMapsAsyncTask#mapId} instance variable for sending a
|
|
||||||
* track to Google Maps.
|
|
||||||
*
|
|
||||||
* @param track the Track
|
|
||||||
* @return true if able to fetch the mapId variable.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean fetchSendMapId(Track track) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean defaultMapPublic = PreferencesUtils.getBoolean(context,
|
|
||||||
R.string.export_google_maps_public_key, PreferencesUtils.EXPORT_GOOGLE_MAPS_PUBLIC_DEFAULT);
|
|
||||||
try {
|
|
||||||
String description = track.getCategory() + "\n" + track.getDescription() + "\n"
|
|
||||||
+ context.getString(R.string.send_google_by_my_tracks, "", "");
|
|
||||||
mapId = SendMapsUtils.createNewMap(
|
|
||||||
track.getName(), description, defaultMapPublic, mapsClient, authToken);
|
|
||||||
shareUrl = MapsClient.buildMapUrl(mapId);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
Log.d(TAG, "Unable to create a new map", e);
|
|
||||||
return false;
|
|
||||||
} catch (HttpException e) {
|
|
||||||
Log.d(TAG, "Unable to create a new map", e);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to create a new map", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mapId != null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads all the points in a track.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean uploadAllTrackPoints(Track track) {
|
|
||||||
int numberOfPoints = track.getNumberOfPoints();
|
|
||||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
|
||||||
Location lastValidLocation = null;
|
|
||||||
boolean sentStartMarker = false;
|
|
||||||
|
|
||||||
// For chart server, limit the number of elevation readings to 250.
|
|
||||||
int elevationSamplingFrequency = Math.max(1, (int) (numberOfPoints / 250.0));
|
|
||||||
Vector<Double> distances = new Vector<Double>();
|
|
||||||
Vector<Double> elevations = new Vector<Double>();
|
|
||||||
TripStatisticsUpdater tripStatisticsUpdater = new TripStatisticsUpdater(
|
|
||||||
track.getTripStatistics().getStartTime());
|
|
||||||
int recordingDistanceInterval = PreferencesUtils.getInt(context,
|
|
||||||
R.string.recording_distance_interval_key,
|
|
||||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
|
||||||
int readCount = 0;
|
|
||||||
LocationIterator locationIterator = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
locationIterator = myTracksProviderUtils.getTrackPointLocationIterator(
|
|
||||||
trackId, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
|
||||||
|
|
||||||
while (locationIterator.hasNext()) {
|
|
||||||
Location location = locationIterator.next();
|
|
||||||
locations.add(location);
|
|
||||||
|
|
||||||
if (LocationUtils.isValidLocation(location)) {
|
|
||||||
lastValidLocation = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sentStartMarker && lastValidLocation != null) {
|
|
||||||
// Create a start marker
|
|
||||||
if (!uploadMarker(context.getString(R.string.marker_label_start, track.getName()), "",
|
|
||||||
START_ICON_URL, lastValidLocation)) {
|
|
||||||
Log.d(TAG, "Unable to create a start marker");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sentStartMarker = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tripStatisticsUpdater.addLocation(
|
|
||||||
location, recordingDistanceInterval, false, ActivityType.INVALID, 0.0);
|
|
||||||
if (readCount % elevationSamplingFrequency == 0) {
|
|
||||||
distances.add(tripStatisticsUpdater.getTripStatistics().getTotalDistance());
|
|
||||||
elevations.add(tripStatisticsUpdater.getSmoothedElevation());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload periodically
|
|
||||||
readCount++;
|
|
||||||
if (readCount % MAX_POINTS_PER_UPLOAD == 0) {
|
|
||||||
if (!prepareAndUploadPoints(track, locations, false)) {
|
|
||||||
Log.d(TAG, "Unable to upload points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
updateProgress(readCount, numberOfPoints);
|
|
||||||
locations.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a final upload with the remaining locations
|
|
||||||
if (!prepareAndUploadPoints(track, locations, true)) {
|
|
||||||
Log.d(TAG, "Unable to upload points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an end marker
|
|
||||||
if (lastValidLocation != null) {
|
|
||||||
distances.add(tripStatisticsUpdater.getTripStatistics().getTotalDistance());
|
|
||||||
elevations.add(tripStatisticsUpdater.getSmoothedElevation());
|
|
||||||
DescriptionGenerator descriptionGenerator = new DescriptionGeneratorImpl(context);
|
|
||||||
track.setDescription(
|
|
||||||
descriptionGenerator.generateTrackDescription(track, distances, elevations, true));
|
|
||||||
if (!uploadMarker(context.getString(R.string.marker_label_end, track.getName()),
|
|
||||||
track.getDescription(), END_ICON_URL, lastValidLocation)) {
|
|
||||||
Log.d(TAG, "Unable to create an end marker");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (locationIterator != null) {
|
|
||||||
locationIterator.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares and uploads a list of locations from a track.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
* @param locations the locations from the track
|
|
||||||
* @param lastBatch true if it is the last batch of locations
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean prepareAndUploadPoints(Track track, List<Location> locations, boolean lastBatch) {
|
|
||||||
// Prepare locations
|
|
||||||
ArrayList<Track> splitTracks = SendToGoogleUtils.prepareLocations(track, locations);
|
|
||||||
|
|
||||||
// Upload segments
|
|
||||||
boolean onlyOneSegment = lastBatch && currentSegment == 1 && splitTracks.size() == 1;
|
|
||||||
for (Track segment : splitTracks) {
|
|
||||||
if (!onlyOneSegment) {
|
|
||||||
segment.setName(context.getString(
|
|
||||||
R.string.send_google_track_part_label, segment.getName(), currentSegment));
|
|
||||||
}
|
|
||||||
if (!uploadSegment(segment.getName(), segment.getLocations())) {
|
|
||||||
Log.d(TAG, "Unable to upload segment");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
currentSegment++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a marker.
|
|
||||||
*
|
|
||||||
* @param title marker title
|
|
||||||
* @param description marker description
|
|
||||||
* @param iconUrl marker marker icon
|
|
||||||
* @param location marker location
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean uploadMarker(String title, String description, String iconUrl, Location location) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!SendMapsUtils.uploadMarker(mapId, title, description, iconUrl, location, mapsClient,
|
|
||||||
authToken, mapsGDataConverter)) {
|
|
||||||
Log.d(TAG, "Unable to upload marker");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (ParseException e) {
|
|
||||||
Log.d(TAG, "Unable to upload marker", e);
|
|
||||||
return false;
|
|
||||||
} catch (HttpException e) {
|
|
||||||
Log.d(TAG, "Unable to upload marker", e);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to upload marker", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a segment
|
|
||||||
*
|
|
||||||
* @param title segment title
|
|
||||||
* @param locations segment locations
|
|
||||||
* @return true if success
|
|
||||||
*/
|
|
||||||
private boolean uploadSegment(String title, ArrayList<Location> locations) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!SendMapsUtils.uploadSegment(
|
|
||||||
mapId, title, locations, mapsClient, authToken, mapsGDataConverter)) {
|
|
||||||
Log.d(TAG, "Unable to upload track points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (ParseException e) {
|
|
||||||
Log.d(TAG, "Unable to upload track points", e);
|
|
||||||
return false;
|
|
||||||
} catch (HttpException e) {
|
|
||||||
Log.d(TAG, "Unable to upload track points", e);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to upload track points", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads all the waypoints.
|
|
||||||
*
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean uploadWaypoints() {
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = myTracksProviderUtils.getWaypointCursor(
|
|
||||||
trackId, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
// This will skip the first waypoint (it carries the stats for the
|
|
||||||
// track).
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Waypoint waypoint = myTracksProviderUtils.createWaypoint(cursor);
|
|
||||||
try {
|
|
||||||
if (!SendMapsUtils.uploadWaypoint(
|
|
||||||
mapId, waypoint, mapsClient, authToken, mapsGDataConverter)) {
|
|
||||||
Log.d(TAG, "Unable to upload waypoint");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (ParseException e) {
|
|
||||||
Log.d(TAG, "Unable to upload waypoint", e);
|
|
||||||
return false;
|
|
||||||
} catch (HttpException e) {
|
|
||||||
Log.d(TAG, "Unable to upload waypoint", e);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "Unable to upload waypoint", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the progress based on the number of locations uploaded.
|
|
||||||
*
|
|
||||||
* @param uploaded the number of uploaded locations
|
|
||||||
* @param total the number of total locations
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
void updateProgress(int uploaded, int total) {
|
|
||||||
publishProgress(getPercentage(uploaded, total));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the percentage of the number of locations uploaded.
|
|
||||||
*
|
|
||||||
* @param uploaded the number of uploaded locations
|
|
||||||
* @param total the number of total locations
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static int getPercentage(int uploaded, int total) {
|
|
||||||
double totalPercentage = (double) uploaded / total;
|
|
||||||
double scaledPercentage = totalPercentage
|
|
||||||
* (PROGRESS_UPLOAD_DATA_MAX - PROGRESS_UPLOAD_DATA_MIN) + PROGRESS_UPLOAD_DATA_MIN;
|
|
||||||
return (int) scaledPercentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the mapID.
|
|
||||||
*
|
|
||||||
* @return mapId
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
String getMapId() {
|
|
||||||
return mapId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of mapsGDataConverter.
|
|
||||||
*
|
|
||||||
* @param mapsGDataConverter new value of mapsGDataConverter
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
void setMapsGDataConverter(MapsGDataConverter mapsGDataConverter) {
|
|
||||||
this.mapsGDataConverter = mapsGDataConverter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.maps;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsClient;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
|
|
||||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsMapMetadata;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.wireless.gdata.client.HttpException;
|
|
||||||
import com.google.wireless.gdata.data.Entry;
|
|
||||||
import com.google.wireless.gdata.parser.ParseException;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for sending a track to Google Maps.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendMapsUtils {
|
|
||||||
|
|
||||||
private static final String EMPTY_TITLE = "-";
|
|
||||||
private static final int LINE_COLOR = 0x80FF0000;
|
|
||||||
private static final String TAG = SendMapsUtils.class.getSimpleName();
|
|
||||||
|
|
||||||
private SendMapsUtils() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Google Map.
|
|
||||||
*
|
|
||||||
* @param title title of the map
|
|
||||||
* @param description description of the map
|
|
||||||
* @param isPublic true if the map can be public
|
|
||||||
* @param mapsClient the maps client
|
|
||||||
* @param authToken the auth token
|
|
||||||
* @return map id of the created map if successful.
|
|
||||||
*/
|
|
||||||
public static String createNewMap(
|
|
||||||
String title, String description, boolean isPublic, MapsClient mapsClient, String authToken)
|
|
||||||
throws ParseException, HttpException, IOException {
|
|
||||||
String mapFeed = MapsClient.getMapsFeed();
|
|
||||||
MapsMapMetadata metaData = new MapsMapMetadata();
|
|
||||||
metaData.setTitle(title);
|
|
||||||
metaData.setDescription(description);
|
|
||||||
metaData.setSearchable(isPublic);
|
|
||||||
Entry entry = MapsGDataConverter.getMapEntryForMetadata(metaData);
|
|
||||||
Entry result = mapsClient.createEntry(mapFeed, authToken, entry);
|
|
||||||
if (result == null) {
|
|
||||||
Log.d(TAG, "No result when creating a new map");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return MapsClient.getMapIdFromMapEntryId(result.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a start/end marker to Google Maps.
|
|
||||||
*
|
|
||||||
* @param mapId the map id
|
|
||||||
* @param title the marker title
|
|
||||||
* @param description the marker description
|
|
||||||
* @param iconUrl the marker icon URL
|
|
||||||
* @param location the marker location
|
|
||||||
* @param mapsClient the maps client
|
|
||||||
* @param authToken the auth token
|
|
||||||
* @param mapsGDataConverter the maps gdata converter
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
public static boolean uploadMarker(String mapId, String title, String description, String iconUrl,
|
|
||||||
Location location, MapsClient mapsClient, String authToken,
|
|
||||||
MapsGDataConverter mapsGDataConverter) throws ParseException, HttpException, IOException {
|
|
||||||
String featuresFeed = MapsClient.getFeaturesFeed(mapId);
|
|
||||||
MapsFeature mapsFeature = buildMapsMarkerFeature(
|
|
||||||
title, description, iconUrl, location);
|
|
||||||
Entry entry = mapsGDataConverter.getEntryForFeature(mapsFeature);
|
|
||||||
try {
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Retry once (often IOException is thrown on a timeout)
|
|
||||||
Log.d(TAG, "Retry upload marker", e);
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a waypoint as a marker feature to Google Maps.
|
|
||||||
*
|
|
||||||
* @param mapId the map id
|
|
||||||
* @param waypoint the waypoint
|
|
||||||
* @param mapsClient the maps client
|
|
||||||
* @param authToken the auth token
|
|
||||||
* @param mapsGDataConverter the maps gdata converter
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
public static boolean uploadWaypoint(String mapId, Waypoint waypoint, MapsClient mapsClient,
|
|
||||||
String authToken, MapsGDataConverter mapsGDataConverter)
|
|
||||||
throws ParseException, HttpException, IOException {
|
|
||||||
String featuresFeed = MapsClient.getFeaturesFeed(mapId);
|
|
||||||
MapsFeature feature = buildMapsMarkerFeature(waypoint.getName(), waypoint.getDescription(),
|
|
||||||
waypoint.getIcon(), waypoint.getLocation());
|
|
||||||
Entry entry = mapsGDataConverter.getEntryForFeature(feature);
|
|
||||||
try {
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Retry once (often IOException is thrown on a timeout)
|
|
||||||
Log.d(TAG, "Retry upload waypoint", e);
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a segment as a line feature to Google Maps.
|
|
||||||
*
|
|
||||||
* @param mapId the map id
|
|
||||||
* @param title the segment title
|
|
||||||
* @param locations the segment locations
|
|
||||||
* @param mapsClient the maps client
|
|
||||||
* @param authToken the auth token
|
|
||||||
* @param mapsGDataConverter the maps gdata converter
|
|
||||||
* @return true if success.
|
|
||||||
*/
|
|
||||||
public static boolean uploadSegment(String mapId, String title, ArrayList<Location> locations,
|
|
||||||
MapsClient mapsClient, String authToken, MapsGDataConverter mapsGDataConverter)
|
|
||||||
throws ParseException, HttpException, IOException {
|
|
||||||
String featuresFeed = MapsClient.getFeaturesFeed(mapId);
|
|
||||||
Entry entry = mapsGDataConverter.getEntryForFeature(buildMapsLineFeature(title, locations));
|
|
||||||
try {
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Retry once (often IOException is thrown on a timeout)
|
|
||||||
Log.d(TAG, "Retry upload track points", e);
|
|
||||||
mapsClient.createEntry(featuresFeed, authToken, entry);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a map marker feature.
|
|
||||||
*
|
|
||||||
* @param title feature title
|
|
||||||
* @param description the feature description
|
|
||||||
* @param iconUrl the feature icon URL
|
|
||||||
* @param location the marker
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static MapsFeature buildMapsMarkerFeature(
|
|
||||||
String title, String description, String iconUrl, Location location) {
|
|
||||||
MapsFeature mapsFeature = new MapsFeature();
|
|
||||||
mapsFeature.setType(MapsFeature.MARKER);
|
|
||||||
mapsFeature.generateAndroidId();
|
|
||||||
// Feature must have a name (otherwise GData upload may fail)
|
|
||||||
mapsFeature.setTitle(TextUtils.isEmpty(title) ? EMPTY_TITLE : title);
|
|
||||||
mapsFeature.setDescription(description.replaceAll("\n", "<br>"));
|
|
||||||
mapsFeature.setIconUrl(iconUrl);
|
|
||||||
mapsFeature.addPoint(location);
|
|
||||||
return mapsFeature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a maps line feature from a set of locations.
|
|
||||||
*
|
|
||||||
* @param title the feature title
|
|
||||||
* @param locations set of locations
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static MapsFeature buildMapsLineFeature(String title, ArrayList<Location> locations) {
|
|
||||||
MapsFeature mapsFeature = new MapsFeature();
|
|
||||||
mapsFeature.setType(MapsFeature.LINE);
|
|
||||||
mapsFeature.generateAndroidId();
|
|
||||||
// Feature must have a name (otherwise GData upload may fail)
|
|
||||||
mapsFeature.setTitle(TextUtils.isEmpty(title) ? EMPTY_TITLE : title);
|
|
||||||
mapsFeature.setColor(LINE_COLOR);
|
|
||||||
for (Location location : locations) {
|
|
||||||
mapsFeature.addPoint(location);
|
|
||||||
}
|
|
||||||
return mapsFeature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-135
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The abstract class for activities sending a track to Google.
|
|
||||||
* <p>
|
|
||||||
* The activity gets recreated when the screen rotates. To support the activity
|
|
||||||
* displaying a progress dialog, we do the following:
|
|
||||||
* <ul>
|
|
||||||
* <li>use one instance of an AyncTask to send the track</li>
|
|
||||||
* <li>save that instance as the last non configuration instance of the activity
|
|
||||||
* </li>
|
|
||||||
* <li>when a new activity is created, pass the activity to the AsyncTask so
|
|
||||||
* that the AsyncTask can update the progress dialog of the activity</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSendActivity extends Activity {
|
|
||||||
|
|
||||||
private static final int DIALOG_PROGRESS_ID = 0;
|
|
||||||
|
|
||||||
protected SendRequest sendRequest;
|
|
||||||
private AbstractSendAsyncTask asyncTask;
|
|
||||||
private ProgressDialog progressDialog;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
|
|
||||||
|
|
||||||
Object retained = getLastNonConfigurationInstance();
|
|
||||||
if (retained instanceof AbstractSendAsyncTask) {
|
|
||||||
asyncTask = (AbstractSendAsyncTask) retained;
|
|
||||||
asyncTask.setActivity(this);
|
|
||||||
} else {
|
|
||||||
asyncTask = createAsyncTask();
|
|
||||||
asyncTask.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object onRetainNonConfigurationInstance() {
|
|
||||||
asyncTask.setActivity(null);
|
|
||||||
return asyncTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
if (id != DIALOG_PROGRESS_ID) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
progressDialog = DialogUtils.createHorizontalProgressDialog(
|
|
||||||
this, R.string.send_google_progress_message, new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
asyncTask.cancel(true);
|
|
||||||
startNextActivity(false, true);
|
|
||||||
}
|
|
||||||
}, getServiceName());
|
|
||||||
return progressDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes when the associated AsyncTask completes.
|
|
||||||
*
|
|
||||||
* @param success true if the AsyncTask is successful
|
|
||||||
*/
|
|
||||||
public void onAsyncTaskCompleted(boolean success, String shareUrl) {
|
|
||||||
sendRequest.setShareUrl(shareUrl);
|
|
||||||
startNextActivity(success, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the progress dialog.
|
|
||||||
*/
|
|
||||||
public void showProgressDialog() {
|
|
||||||
showDialog(DIALOG_PROGRESS_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the progress dialog value.
|
|
||||||
*
|
|
||||||
* @param value the dialog value
|
|
||||||
*/
|
|
||||||
public void setProgressDialogValue(int value) {
|
|
||||||
if (progressDialog != null) {
|
|
||||||
progressDialog.setIndeterminate(false);
|
|
||||||
progressDialog.setProgress(value);
|
|
||||||
progressDialog.setMax(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the AsyncTask.
|
|
||||||
*/
|
|
||||||
protected abstract AbstractSendAsyncTask createAsyncTask();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the service name.
|
|
||||||
*/
|
|
||||||
protected abstract String getServiceName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the next activity.
|
|
||||||
*
|
|
||||||
* @param success true if this activity is successful
|
|
||||||
* @param isCancel true if it is a cancel request
|
|
||||||
*/
|
|
||||||
protected abstract void startNextActivity(boolean success, boolean isCancel);
|
|
||||||
}
|
|
||||||
-143
@@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The abstract class for AsyncTasks sending a track to Google.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The activity associated with this AsyncTask.
|
|
||||||
*/
|
|
||||||
private AbstractSendActivity activity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the AsyncTask result is success.
|
|
||||||
*/
|
|
||||||
private boolean success;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The share url from the AsyncTask.
|
|
||||||
*/
|
|
||||||
protected String shareUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the AsyncTask has completed.
|
|
||||||
*/
|
|
||||||
private boolean completed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if can retry the AsyncTask.
|
|
||||||
*/
|
|
||||||
private boolean canRetry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an AsyncTask.
|
|
||||||
*
|
|
||||||
* @param activity the activity currently associated with this AsyncTask
|
|
||||||
*/
|
|
||||||
public AbstractSendAsyncTask(AbstractSendActivity activity) {
|
|
||||||
this.activity = activity;
|
|
||||||
success = false;
|
|
||||||
shareUrl = null;
|
|
||||||
completed = false;
|
|
||||||
canRetry = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current activity associated with this AyncTask.
|
|
||||||
*
|
|
||||||
* @param activity the current activity, can be null
|
|
||||||
*/
|
|
||||||
public void setActivity(AbstractSendActivity activity) {
|
|
||||||
this.activity = activity;
|
|
||||||
if (completed && activity != null) {
|
|
||||||
activity.onAsyncTaskCompleted(success, shareUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
activity.showProgressDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
try {
|
|
||||||
return performTask();
|
|
||||||
} finally {
|
|
||||||
closeConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate(Integer... values) {
|
|
||||||
if (activity != null) {
|
|
||||||
activity.setProgressDialogValue(values[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
success = result;
|
|
||||||
completed = true;
|
|
||||||
if (activity != null) {
|
|
||||||
activity.onAsyncTaskCompleted(success, shareUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retries the task. First, invalidates the auth token. If can retry, invokes
|
|
||||||
* {@link #performTask()}. Returns false if cannot retry.
|
|
||||||
*
|
|
||||||
* @return the result of the retry.
|
|
||||||
*/
|
|
||||||
protected boolean retryTask() {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidateToken();
|
|
||||||
if (canRetry) {
|
|
||||||
canRetry = false;
|
|
||||||
return performTask();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes any AsyncTask connection.
|
|
||||||
*/
|
|
||||||
protected abstract void closeConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the AsyncTask.
|
|
||||||
*
|
|
||||||
* @return true if success
|
|
||||||
*/
|
|
||||||
protected abstract boolean performTask();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidates the auth token.
|
|
||||||
*/
|
|
||||||
protected abstract void invalidateToken();
|
|
||||||
}
|
|
||||||
-218
@@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send request states for sending a track to Google Drive, Google Maps, Google
|
|
||||||
* Fusion Tables, and Google Spreadsheets.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendRequest implements Parcelable {
|
|
||||||
|
|
||||||
public static final String SEND_REQUEST_KEY = "sendRequest";
|
|
||||||
|
|
||||||
private long trackId = -1L;
|
|
||||||
private boolean sendDrive = false;
|
|
||||||
private boolean sendMaps = false;
|
|
||||||
private boolean sendFusionTables = false;
|
|
||||||
private boolean sendSpreadsheets = false;
|
|
||||||
|
|
||||||
private boolean driveSync = false; // to enable Drive sync
|
|
||||||
private boolean driveSharePublic = false; // for driveShare, share as public
|
|
||||||
private String driveShareEmails = null; // for driveShare, emails to share
|
|
||||||
|
|
||||||
private Account account = null;
|
|
||||||
|
|
||||||
private boolean driveSuccess = false;
|
|
||||||
private boolean mapsSuccess = false;
|
|
||||||
private boolean spreadsheetsSuccess = false;
|
|
||||||
private boolean fusionTablesSuccess = false;
|
|
||||||
private String shareUrl = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new send request.
|
|
||||||
*
|
|
||||||
* @param trackId the track id
|
|
||||||
*/
|
|
||||||
public SendRequest(long trackId) {
|
|
||||||
this.trackId = trackId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTrackId() {
|
|
||||||
return trackId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSendDrive() {
|
|
||||||
return sendDrive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendDrive(boolean sendDrive) {
|
|
||||||
this.sendDrive = sendDrive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSendMaps() {
|
|
||||||
return sendMaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendMaps(boolean sendMaps) {
|
|
||||||
this.sendMaps = sendMaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSendFusionTables() {
|
|
||||||
return sendFusionTables;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendFusionTables(boolean sendFusionTables) {
|
|
||||||
this.sendFusionTables = sendFusionTables;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSendSpreadsheets() {
|
|
||||||
return sendSpreadsheets;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendSpreadsheets(boolean sendSpreadsheets) {
|
|
||||||
this.sendSpreadsheets = sendSpreadsheets;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDriveSync() {
|
|
||||||
return driveSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDriveSync(boolean driveSync) {
|
|
||||||
this.driveSync = driveSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDriveSharePublic() {
|
|
||||||
return driveSharePublic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDriveSharePublic(boolean driveSharePublic) {
|
|
||||||
this.driveSharePublic = driveSharePublic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDriveShareEmails() {
|
|
||||||
return driveShareEmails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDriveShareEmails(String driveShareEmails) {
|
|
||||||
this.driveShareEmails = driveShareEmails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Account getAccount() {
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccount(Account account) {
|
|
||||||
this.account = account;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDriveSuccess() {
|
|
||||||
return driveSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDriveSuccess(boolean driveSuccess) {
|
|
||||||
this.driveSuccess = driveSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMapsSuccess() {
|
|
||||||
return mapsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMapsSuccess(boolean mapsSuccess) {
|
|
||||||
this.mapsSuccess = mapsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFusionTablesSuccess() {
|
|
||||||
return fusionTablesSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFusionTablesSuccess(boolean fusionTablesSuccess) {
|
|
||||||
this.fusionTablesSuccess = fusionTablesSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSpreadsheetsSuccess() {
|
|
||||||
return spreadsheetsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpreadsheetsSuccess(boolean spreadsheetsSuccess) {
|
|
||||||
this.spreadsheetsSuccess = spreadsheetsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShareUrl() {
|
|
||||||
return shareUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShareUrl(String shareUrl) {
|
|
||||||
this.shareUrl = shareUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SendRequest(Parcel in) {
|
|
||||||
trackId = in.readLong();
|
|
||||||
sendDrive = in.readByte() == 1;
|
|
||||||
sendMaps = in.readByte() == 1;
|
|
||||||
sendFusionTables = in.readByte() == 1;
|
|
||||||
sendSpreadsheets = in.readByte() == 1;
|
|
||||||
driveSync = in.readByte() == 1;
|
|
||||||
driveSharePublic = in.readByte() == 1;
|
|
||||||
driveShareEmails = in.readString();
|
|
||||||
account = in.readParcelable(null);
|
|
||||||
driveSuccess = in.readByte() == 1;
|
|
||||||
mapsSuccess = in.readByte() == 1;
|
|
||||||
fusionTablesSuccess = in.readByte() == 1;
|
|
||||||
spreadsheetsSuccess = in.readByte() == 1;
|
|
||||||
shareUrl = in.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
|
||||||
out.writeLong(trackId);
|
|
||||||
out.writeByte((byte) (sendDrive ? 1 : 0));
|
|
||||||
out.writeByte((byte) (sendMaps ? 1 : 0));
|
|
||||||
out.writeByte((byte) (sendFusionTables ? 1 : 0));
|
|
||||||
out.writeByte((byte) (sendSpreadsheets ? 1 : 0));
|
|
||||||
out.writeByte((byte) (driveSync ? 1 : 0));
|
|
||||||
out.writeByte((byte) (driveSharePublic ? 1 : 0));
|
|
||||||
out.writeString(driveShareEmails);
|
|
||||||
out.writeParcelable(account, 0);
|
|
||||||
out.writeByte((byte) (driveSuccess ? 1 : 0));
|
|
||||||
out.writeByte((byte) (mapsSuccess ? 1 : 0));
|
|
||||||
out.writeByte((byte) (fusionTablesSuccess ? 1 : 0));
|
|
||||||
out.writeByte((byte) (spreadsheetsSuccess ? 1 : 0));
|
|
||||||
out.writeString(shareUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<SendRequest>
|
|
||||||
CREATOR = new Parcelable.Creator<SendRequest>() {
|
|
||||||
public SendRequest createFromParcel(Parcel in) {
|
|
||||||
return new SendRequest(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SendRequest[] newArray(int size) {
|
|
||||||
return new SendRequest[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
-204
@@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
|
||||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
|
||||||
import com.google.api.services.drive.DriveScopes;
|
|
||||||
import com.google.api.services.fusiontables.FusiontablesScopes;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commons utilities for sending a track to Google.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendToGoogleUtils {
|
|
||||||
|
|
||||||
private static final String TAG = SendToGoogleUtils.class.getSimpleName();
|
|
||||||
|
|
||||||
public static final String DRIVE_SCOPE = DriveScopes.DRIVE;
|
|
||||||
public static final int DRIVE_NOTIFICATION_ID = 1;
|
|
||||||
|
|
||||||
public static final String FUSION_TABLES_SCOPE = FusiontablesScopes.FUSIONTABLES;
|
|
||||||
public static final int FUSION_TABLES_NOTIFICATION_ID = 2;
|
|
||||||
|
|
||||||
public static final String SPREADSHEETS_SCOPE = "https://spreadsheets.google.com/feeds";
|
|
||||||
public static final int SPREADSHEETS_NOTIFICATION_ID = 3;
|
|
||||||
|
|
||||||
private SendToGoogleUtils() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares a list of locations to send to Google Maps or Google Fusion
|
|
||||||
* Tables. Splits the locations into segments if necessary.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
* @param locations the list of locations
|
|
||||||
* @return an array of split segments.
|
|
||||||
*/
|
|
||||||
public static ArrayList<Track> prepareLocations(Track track, List<Location> locations) {
|
|
||||||
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
|
||||||
|
|
||||||
// Create a new segment
|
|
||||||
Track segment = createNewSegment(
|
|
||||||
track, locations.size() > 0 ? locations.get(0).getTime() : -1L);
|
|
||||||
|
|
||||||
for (Location location : locations) {
|
|
||||||
/*
|
|
||||||
* Latitude is greater than 90 if the location is a pause/resume
|
|
||||||
* separator.
|
|
||||||
*/
|
|
||||||
if (location.getLatitude() > 90) {
|
|
||||||
endSegment(segment, location.getTime(), splitTracks);
|
|
||||||
segment = createNewSegment(track, location.getTime());
|
|
||||||
} else {
|
|
||||||
segment.addLocation(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endSegment(segment, locations.size() > 0 ? locations.get(locations.size() - 1).getTime() : -1L,
|
|
||||||
splitTracks);
|
|
||||||
return splitTracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new segment for a track.
|
|
||||||
*
|
|
||||||
* @param track the track
|
|
||||||
* @param startTime the segment start time
|
|
||||||
*/
|
|
||||||
private static Track createNewSegment(Track track, long startTime) {
|
|
||||||
Track segment = new Track();
|
|
||||||
segment.setId(track.getId());
|
|
||||||
segment.setName(track.getName());
|
|
||||||
segment.setDescription("");
|
|
||||||
segment.setCategory(track.getCategory());
|
|
||||||
TripStatistics segmentTripStatistics = segment.getTripStatistics();
|
|
||||||
segmentTripStatistics.setStartTime(startTime);
|
|
||||||
return segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends a segment. Adds to the array of track segments if the segment is
|
|
||||||
* valid.
|
|
||||||
*
|
|
||||||
* @param segment the segment
|
|
||||||
* @param stopTime the stop time
|
|
||||||
* @param splitTracks the array of track segments
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static boolean endSegment(Track segment, long stopTime, ArrayList<Track> splitTracks) {
|
|
||||||
// Make sure the segment has at least 2 points
|
|
||||||
if (segment.getLocations().size() < 2) {
|
|
||||||
Log.d(TAG, "segment has less than 2 points");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set its stop time
|
|
||||||
segment.getTripStatistics().setStopTime(stopTime);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decimate to 2 meter precision. Google Maps and Google Fusion Tables do
|
|
||||||
* not like the locations to be too precise.
|
|
||||||
*/
|
|
||||||
LocationUtils.decimate(segment, 2.0);
|
|
||||||
|
|
||||||
splitTracks.add(segment);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the google account credential.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
* @param accountName the account name
|
|
||||||
* @param scope the scope
|
|
||||||
*/
|
|
||||||
public static GoogleAccountCredential getGoogleAccountCredential(
|
|
||||||
Context context, String accountName, String scope) throws IOException, GoogleAuthException {
|
|
||||||
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context, scope);
|
|
||||||
credential.setSelectedAccountName(accountName);
|
|
||||||
credential.getToken();
|
|
||||||
return credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the OAuth2 token.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
* @param accountName the account name
|
|
||||||
* @param scope the scope
|
|
||||||
*/
|
|
||||||
public static String getToken(Context context, String accountName, String scope)
|
|
||||||
throws IOException, GoogleAuthException {
|
|
||||||
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context, scope);
|
|
||||||
credential.setSelectedAccountName(accountName);
|
|
||||||
return credential.getToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a notification to request permission.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
* @param accountName the account name
|
|
||||||
* @param intent the intent
|
|
||||||
* @param notificaitonId the notification id
|
|
||||||
*/
|
|
||||||
public static void sendNotification(
|
|
||||||
Context context, String accountName, Intent intent, int notificaitonId) {
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).addFlags(Intent.FLAG_FROM_BACKGROUND);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(
|
|
||||||
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context).setAutoCancel(true)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setContentText(context.getString(R.string.permission_request_message, accountName))
|
|
||||||
.setContentTitle(context.getString(R.string.permission_request_title))
|
|
||||||
.setSmallIcon(android.R.drawable.ic_dialog_alert)
|
|
||||||
.setTicker(context.getString(R.string.permission_request_title));
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
|
|
||||||
Context.NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.notify(notificaitonId, builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels any notification to request a permission.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
* @param notificationId the notification id
|
|
||||||
*/
|
|
||||||
public static void cancelNotification(Context context, int notificationId) {
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
|
|
||||||
Context.NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.cancel(notificationId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-160
@@ -1,160 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.sendtogoogle;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment;
|
|
||||||
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment.ChooseActivityCaller;
|
|
||||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dialog to show the result of uploading to Google services.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class UploadResultActivity extends FragmentActivity implements ChooseActivityCaller {
|
|
||||||
|
|
||||||
private static final String TAG = UploadResultActivity.class.getSimpleName();
|
|
||||||
@VisibleForTesting
|
|
||||||
static final int DIALOG_RESULT_ID = 0;
|
|
||||||
@VisibleForTesting
|
|
||||||
protected View view;
|
|
||||||
|
|
||||||
private SendRequest sendRequest;
|
|
||||||
private String shareUrl;
|
|
||||||
private Dialog resultDialog;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
|
|
||||||
shareUrl = sendRequest.getShareUrl();
|
|
||||||
|
|
||||||
Track track = MyTracksProviderUtils.Factory.get(this).getTrack(sendRequest.getTrackId());
|
|
||||||
if (track == null) {
|
|
||||||
Log.d(TAG, "No track for " + sendRequest.getTrackId());
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendRequest.isDriveSuccess() && shareUrl != null) {
|
|
||||||
new ChooseActivityDialogFragment().show(
|
|
||||||
getSupportFragmentManager(), ChooseActivityDialogFragment.CHOOSE_ACTIVITY_DIALOG_TAG);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
showDialog(DIALOG_RESULT_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
if (id != DIALOG_RESULT_ID) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int serviceName;
|
|
||||||
int serviceUrl;
|
|
||||||
boolean success;
|
|
||||||
if (sendRequest.isSendDrive()) {
|
|
||||||
serviceName = R.string.export_google_drive;
|
|
||||||
serviceUrl = R.string.export_google_drive_url;
|
|
||||||
success = sendRequest.isDriveSuccess();
|
|
||||||
} else if (sendRequest.isSendMaps()) {
|
|
||||||
serviceName = R.string.export_google_maps;
|
|
||||||
serviceUrl = R.string.export_google_maps_url;
|
|
||||||
success = sendRequest.isMapsSuccess();
|
|
||||||
} else if (sendRequest.isSendFusionTables()) {
|
|
||||||
serviceName = R.string.export_google_fusion_tables;
|
|
||||||
serviceUrl = R.string.export_google_fusion_tables_url;
|
|
||||||
success = sendRequest.isFusionTablesSuccess();
|
|
||||||
} else {
|
|
||||||
serviceName = R.string.export_google_spreadsheets;
|
|
||||||
serviceUrl = R.string.export_google_spreadsheets_url;
|
|
||||||
success = sendRequest.isSpreadsheetsSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
int messageId;
|
|
||||||
if (success) {
|
|
||||||
messageId = R.string.export_google_success;
|
|
||||||
} else {
|
|
||||||
if (sendRequest.isDriveSharePublic()) {
|
|
||||||
messageId = R.string.export_google_error_public;
|
|
||||||
} else {
|
|
||||||
messageId = R.string.export_google_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String message = getString(messageId, getString(serviceName), getString(serviceUrl));
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this).setCancelable(true)
|
|
||||||
.setIcon(success ? R.drawable.ic_dialog_success : android.R.drawable.ic_dialog_alert)
|
|
||||||
.setMessage(message)
|
|
||||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setTitle(success ? R.string.generic_success_title : R.string.generic_error_title);
|
|
||||||
|
|
||||||
// Add a Share URL button if shareUrl exists
|
|
||||||
if (success && shareUrl != null) {
|
|
||||||
builder.setNegativeButton(
|
|
||||||
R.string.share_track_share_url, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
new ChooseActivityDialogFragment().show(getSupportFragmentManager(),
|
|
||||||
ChooseActivityDialogFragment.CHOOSE_ACTIVITY_DIALOG_TAG);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resultDialog = builder.create();
|
|
||||||
resultDialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShow(DialogInterface dialog) {
|
|
||||||
DialogUtils.setDialogTitleDivider(UploadResultActivity.this, resultDialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return resultDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChooseActivityDone(String packageName, String className) {
|
|
||||||
if (packageName != null && className != null) {
|
|
||||||
Intent intent = IntentUtils.newShareUrlIntent(
|
|
||||||
this, sendRequest.getTrackId(), shareUrl, packageName, className);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-53
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.spreadsheets;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An activity to send a track to Google Spreadsheet.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendSpreadsheetsActivity extends AbstractSendActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractSendAsyncTask createAsyncTask() {
|
|
||||||
return new SendSpreadsheetsAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getServiceName() {
|
|
||||||
return getString(R.string.export_google_spreadsheets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void startNextActivity(boolean success, boolean isCancel) {
|
|
||||||
sendRequest.setSpreadsheetsSuccess(success);
|
|
||||||
Intent intent = IntentUtils.newIntent(this, UploadResultActivity.class)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-282
@@ -1,282 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.spreadsheets;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.StringUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
|
||||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
import com.google.api.client.auth.oauth2.BearerToken;
|
|
||||||
import com.google.api.client.auth.oauth2.Credential;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
|
||||||
import com.google.api.client.http.ByteArrayContent;
|
|
||||||
import com.google.api.services.drive.Drive;
|
|
||||||
import com.google.api.services.drive.model.File;
|
|
||||||
import com.google.api.services.drive.model.FileList;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
|
||||||
import com.google.gdata.data.spreadsheet.ListEntry;
|
|
||||||
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
|
||||||
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
|
||||||
import com.google.gdata.util.ServiceException;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AsyncTask to send a track to Google Spreadsheet.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendSpreadsheetsAsyncTask extends AbstractSendAsyncTask {
|
|
||||||
|
|
||||||
private static final String TAG = SendSpreadsheetsAsyncTask.class.getSimpleName();
|
|
||||||
private static final String
|
|
||||||
GOOGLE_SPREADSHEET_MIME_TYPE = "application/vnd.google-apps.spreadsheet";
|
|
||||||
private static final String
|
|
||||||
OPENDOCUMENT_SPREADSHEET_MIME_TYPE = "application/x-vnd.oasis.opendocument.spreadsheet";
|
|
||||||
@VisibleForTesting
|
|
||||||
public static final String GET_SPREADSHEET_QUERY =
|
|
||||||
"'root' in parents and title = '%s' and mimeType = '" + GOOGLE_SPREADSHEET_MIME_TYPE
|
|
||||||
+ "' and trashed = false";
|
|
||||||
@VisibleForTesting
|
|
||||||
public static final String
|
|
||||||
GET_WORKSHEETS_URI = "https://spreadsheets.google.com/feeds/worksheets/%s/private/full";
|
|
||||||
|
|
||||||
private static final int PROGRESS_GET_SPREADSHEET_ID = 0;
|
|
||||||
private static final int PROGRESS_GET_WORKSHEET_URL = 35;
|
|
||||||
private static final int PROGRESS_ADD_TRACK_INFO = 70;
|
|
||||||
private static final int PROGRESS_COMPLETE = 100;
|
|
||||||
|
|
||||||
private final long trackId;
|
|
||||||
private final Account account;
|
|
||||||
private final Context context;
|
|
||||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
|
||||||
|
|
||||||
public SendSpreadsheetsAsyncTask(SendSpreadsheetsActivity activity, long trackId, Account account) {
|
|
||||||
super(activity);
|
|
||||||
this.trackId = trackId;
|
|
||||||
this.account = account;
|
|
||||||
|
|
||||||
context = activity.getApplicationContext();
|
|
||||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void closeConnection() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performTask() {
|
|
||||||
try {
|
|
||||||
SpreadsheetService spreadsheetService = new SpreadsheetService(
|
|
||||||
"MyTracks-" + SystemUtils.getMyTracksVersion(context));
|
|
||||||
Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod());
|
|
||||||
|
|
||||||
credential.setAccessToken(
|
|
||||||
SendToGoogleUtils.getToken(context, account.name, SendToGoogleUtils.SPREADSHEETS_SCOPE));
|
|
||||||
spreadsheetService.setOAuth2Credentials(credential);
|
|
||||||
|
|
||||||
Track track = myTracksProviderUtils.getTrack(trackId);
|
|
||||||
if (track == null) {
|
|
||||||
Log.d(TAG, "No track for " + trackId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String title = context.getString(R.string.my_tracks_app_name);
|
|
||||||
if (track.getCategory() != null && !track.getCategory().equals("")) {
|
|
||||||
title += "-" + track.getCategory();
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_GET_SPREADSHEET_ID);
|
|
||||||
String spreadsheetId = getSpreadSheetId(title);
|
|
||||||
if (spreadsheetId == null) {
|
|
||||||
Log.d(TAG, "Unable to get the spreadsheet ID for " + title);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_GET_WORKSHEET_URL);
|
|
||||||
URL worksheetUrl = getWorksheetUrl(spreadsheetService, spreadsheetId);
|
|
||||||
if (worksheetUrl == null) {
|
|
||||||
Log.d(TAG, "Unable to get the worksheet url for " + spreadsheetId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_ADD_TRACK_INFO);
|
|
||||||
if (!addTrackInfo(spreadsheetService, worksheetUrl, track)) {
|
|
||||||
Log.d(TAG, "Unable to add track info");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(PROGRESS_COMPLETE);
|
|
||||||
return true;
|
|
||||||
} catch (UserRecoverableAuthException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.SPREADSHEETS_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (GoogleAuthException e) {
|
|
||||||
Log.e(TAG, "GoogleaAuthException", e);
|
|
||||||
return retryTask();
|
|
||||||
} catch (UserRecoverableAuthIOException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.SPREADSHEETS_NOTIFICATION_ID);
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "IOException", e);
|
|
||||||
return retryTask();
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
Log.e(TAG, "ServiceException", e);
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidateToken() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the spreadsheet id.
|
|
||||||
*
|
|
||||||
* @param fileName the file name
|
|
||||||
*/
|
|
||||||
private String getSpreadSheetId(String fileName) throws IOException, GoogleAuthException {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
GoogleAccountCredential driveCredential = SendToGoogleUtils.getGoogleAccountCredential(
|
|
||||||
context, account.name, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
if (driveCredential == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Drive drive = SyncUtils.getDriveService(driveCredential);
|
|
||||||
com.google.api.services.drive.Drive.Files.List list = drive.files()
|
|
||||||
.list().setQ(String.format(Locale.US, GET_SPREADSHEET_QUERY, fileName));
|
|
||||||
FileList result = list.execute();
|
|
||||||
for (File file : result.getItems()) {
|
|
||||||
if (file.getSharedWithMeDate() == null) {
|
|
||||||
return file.getId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isCancelled()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
InputStream inputStream = null;
|
|
||||||
try {
|
|
||||||
inputStream = context.getResources().openRawResource(R.raw.mytracks_empty_spreadsheet);
|
|
||||||
byte[] b = new byte[inputStream.available()];
|
|
||||||
inputStream.read(b);
|
|
||||||
ByteArrayContent fileContent = new ByteArrayContent(OPENDOCUMENT_SPREADSHEET_MIME_TYPE, b);
|
|
||||||
|
|
||||||
File file = new File();
|
|
||||||
file.setTitle(fileName);
|
|
||||||
file.setMimeType(OPENDOCUMENT_SPREADSHEET_MIME_TYPE);
|
|
||||||
return drive.files().insert(file, fileContent).setConvert(true).execute().getId();
|
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the worksheet url.
|
|
||||||
*
|
|
||||||
* @param spreadsheetService the spreadsheet service
|
|
||||||
* @param spreadsheetId the spreadsheet id
|
|
||||||
*/
|
|
||||||
private URL getWorksheetUrl(SpreadsheetService spreadsheetService, String spreadsheetId)
|
|
||||||
throws IOException, ServiceException {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
URL url = new URL(String.format(Locale.US, GET_WORKSHEETS_URI, spreadsheetId));
|
|
||||||
WorksheetFeed feed = spreadsheetService.getFeed(url, WorksheetFeed.class);
|
|
||||||
List<WorksheetEntry> worksheets = feed.getEntries();
|
|
||||||
|
|
||||||
if (worksheets.size() > 0) {
|
|
||||||
return worksheets.get(0).getListFeedUrl();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds track info to a worksheet.
|
|
||||||
*
|
|
||||||
* @param spreadsheetService the spreadsheet service
|
|
||||||
* @param worksheetUrl the worksheet url
|
|
||||||
* @param track the track
|
|
||||||
* @return true if completes.
|
|
||||||
*/
|
|
||||||
private boolean addTrackInfo(SpreadsheetService spreadsheetService, URL worksheetUrl, Track track)
|
|
||||||
throws IOException, ServiceException {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TripStatistics tripStatistics = track.getTripStatistics();
|
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
|
|
||||||
String distanceUnit = context.getString(
|
|
||||||
metricUnits ? R.string.unit_kilometer : R.string.unit_mile);
|
|
||||||
String speedUnit = context.getString(
|
|
||||||
metricUnits ? R.string.unit_kilometer_per_hour : R.string.unit_mile_per_hour);
|
|
||||||
String elevationUnit = context.getString(
|
|
||||||
metricUnits ? R.string.unit_meter : R.string.unit_feet);
|
|
||||||
ListEntry row = new ListEntry();
|
|
||||||
|
|
||||||
row.getCustomElements().setValueLocal("name", track.getName());
|
|
||||||
row.getCustomElements().setValueLocal("description", track.getDescription());
|
|
||||||
row.getCustomElements()
|
|
||||||
.setValueLocal("date", StringUtils.formatDateTime(context, tripStatistics.getStartTime()));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"totaltime", StringUtils.formatElapsedTimeWithHour(tripStatistics.getTotalTime()));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"movingtime", StringUtils.formatElapsedTimeWithHour(tripStatistics.getMovingTime()));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"distance", SendSpreadsheetsUtils.getDistance(tripStatistics.getTotalDistance(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal("distanceunit", distanceUnit);
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"averagespeed", SendSpreadsheetsUtils.getSpeed(tripStatistics.getAverageSpeed(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal("averagemovingspeed",
|
|
||||||
SendSpreadsheetsUtils.getSpeed(tripStatistics.getAverageMovingSpeed(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"maxspeed", SendSpreadsheetsUtils.getSpeed(tripStatistics.getMaxSpeed(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal("speedunit", speedUnit);
|
|
||||||
row.getCustomElements().setValueLocal("elevationgain",
|
|
||||||
SendSpreadsheetsUtils.getElevation(tripStatistics.getTotalElevationGain(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"minelevation", SendSpreadsheetsUtils.getElevation(tripStatistics.getMinElevation(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal(
|
|
||||||
"maxelevation", SendSpreadsheetsUtils.getElevation(tripStatistics.getMaxElevation(), metricUnits));
|
|
||||||
row.getCustomElements().setValueLocal("elevationunit", elevationUnit);
|
|
||||||
|
|
||||||
ListEntry result = spreadsheetService.insert(worksheetUrl, row);
|
|
||||||
return result != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-79
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 com.google.android.apps.mytracks.io.spreadsheets;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for sending a track to Google Spreadsheet.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
public class SendSpreadsheetsUtils {
|
|
||||||
|
|
||||||
// Google Spreadsheet can only parse numbers in the English locale.
|
|
||||||
private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance(Locale.ENGLISH);
|
|
||||||
private static final NumberFormat INTEGER_FORMAT = NumberFormat.getIntegerInstance(
|
|
||||||
Locale.ENGLISH);
|
|
||||||
|
|
||||||
static {
|
|
||||||
NUMBER_FORMAT.setMaximumFractionDigits(2);
|
|
||||||
NUMBER_FORMAT.setMinimumFractionDigits(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SendSpreadsheetsUtils() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the distance. Performs unit conversion and formatting.
|
|
||||||
*
|
|
||||||
* @param distanceInMeter the distance in meters
|
|
||||||
* @param metricUnits true to use metric
|
|
||||||
*/
|
|
||||||
public static final String getDistance(double distanceInMeter, boolean metricUnits) {
|
|
||||||
double distanceInKilometer = distanceInMeter * UnitConversions.M_TO_KM;
|
|
||||||
double distance = metricUnits ? distanceInKilometer
|
|
||||||
: distanceInKilometer * UnitConversions.KM_TO_MI;
|
|
||||||
return NUMBER_FORMAT.format(distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the speed. Performs unit conversion and formatting.
|
|
||||||
*
|
|
||||||
* @param speedInMeterPerSecond the speed in meters per second
|
|
||||||
* @param metricUnits true to use metric
|
|
||||||
*/
|
|
||||||
public static final String getSpeed(double speedInMeterPerSecond, boolean metricUnits) {
|
|
||||||
double speedInKilometerPerHour = speedInMeterPerSecond * UnitConversions.MS_TO_KMH;
|
|
||||||
double speed = metricUnits ? speedInKilometerPerHour
|
|
||||||
: speedInKilometerPerHour * UnitConversions.KM_TO_MI;
|
|
||||||
return NUMBER_FORMAT.format(speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the elevation. Performs unit conversion and formatting.
|
|
||||||
*
|
|
||||||
* @param elevationInMeter the elevation value in meters
|
|
||||||
* @param metricUnits true to use metric
|
|
||||||
*/
|
|
||||||
public static final String getElevation(double elevationInMeter, boolean metricUnits) {
|
|
||||||
double elevation = metricUnits ? elevationInMeter : elevationInMeter * UnitConversions.M_TO_FT;
|
|
||||||
return INTEGER_FORMAT.format(elevation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@ import com.google.android.apps.mytracks.io.file.exporter.KmzTrackExporter;
|
|||||||
import com.google.android.apps.mytracks.io.file.importer.KmlFileTrackImporter;
|
import com.google.android.apps.mytracks.io.file.importer.KmlFileTrackImporter;
|
||||||
import com.google.android.apps.mytracks.io.file.importer.KmzTrackImporter;
|
import com.google.android.apps.mytracks.io.file.importer.KmzTrackImporter;
|
||||||
import com.google.android.apps.mytracks.io.file.importer.TrackImporter;
|
import com.google.android.apps.mytracks.io.file.importer.TrackImporter;
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.FileUtils;
|
import com.google.android.apps.mytracks.util.FileUtils;
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
import com.google.android.gms.auth.GoogleAuthException;
|
||||||
@@ -97,49 +96,6 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
if (account == null) {
|
if (account == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String googleAccount = PreferencesUtils.getString(
|
|
||||||
context, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
|
||||||
if (googleAccount == null || googleAccount.equals(PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!googleAccount.equals(account.name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
GoogleAccountCredential credential = SendToGoogleUtils.getGoogleAccountCredential(
|
|
||||||
context, account.name, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
if (credential == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drive == null || !driveAccountName.equals(account.name)) {
|
|
||||||
drive = SyncUtils.getDriveService(credential);
|
|
||||||
driveAccountName = account.name;
|
|
||||||
}
|
|
||||||
folderId = getFolderId();
|
|
||||||
|
|
||||||
long largestChangeId = PreferencesUtils.getLong(
|
|
||||||
context, R.string.drive_largest_change_id_key);
|
|
||||||
if (largestChangeId == PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT) {
|
|
||||||
performInitialSync();
|
|
||||||
} else {
|
|
||||||
performIncrementalSync(largestChangeId);
|
|
||||||
}
|
|
||||||
insertNewDriveFiles();
|
|
||||||
} catch (UserRecoverableAuthException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
} catch (GoogleAuthException e) {
|
|
||||||
Log.e(TAG, "GoogleAuthException", e);
|
|
||||||
} catch (UserRecoverableAuthIOException e) {
|
|
||||||
SendToGoogleUtils.sendNotification(
|
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "IOException", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-41
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.android.apps.mytracks.services.tasks;
|
package com.google.android.apps.mytracks.services.tasks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.gms.auth.GoogleAuthException;
|
import com.google.android.gms.auth.GoogleAuthException;
|
||||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
import com.google.android.gms.auth.UserRecoverableAuthException;
|
||||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
||||||
@@ -85,7 +84,7 @@ public class CheckPermissionAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
return performTask();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -97,43 +96,4 @@ public class CheckPermissionAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
|||||||
scope, success, userRecoverableIntent);
|
scope, success, userRecoverableIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean performTask() {
|
|
||||||
try {
|
|
||||||
SendToGoogleUtils.getGoogleAccountCredential(activity, accountName, scope);
|
|
||||||
return true;
|
|
||||||
} catch (UserRecoverableAuthException e) {
|
|
||||||
try {
|
|
||||||
// HACK: UserRecoverableAuthException.getIntent can throw a null pointer
|
|
||||||
// exception.
|
|
||||||
userRecoverableIntent = e.getIntent();
|
|
||||||
return false;
|
|
||||||
} catch (Exception e1) {
|
|
||||||
Log.e(TAG, "Exception in getIntent", e1);
|
|
||||||
userRecoverableIntent = null;
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
} catch (GoogleAuthException e) {
|
|
||||||
Log.e(TAG, "GoogleAuthException", e);
|
|
||||||
return retryTask();
|
|
||||||
} catch (UserRecoverableAuthIOException e) {
|
|
||||||
userRecoverableIntent = e.getIntent();
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "IOException", e);
|
|
||||||
return retryTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean retryTask() {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canRetry) {
|
|
||||||
canRetry = false;
|
|
||||||
return performTask();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
-61
@@ -17,7 +17,6 @@
|
|||||||
package com.google.android.apps.mytracks.settings;
|
package com.google.android.apps.mytracks.settings;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
|
||||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||||
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
||||||
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask.CheckPermissionCaller;
|
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask.CheckPermissionCaller;
|
||||||
@@ -131,50 +130,6 @@ public class SettingsActivity extends AbstractSettingsActivity implements CheckP
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case DIALOG_CHOOSE_ACCOUNT:
|
|
||||||
Account[] accounts = AccountManager.get(SettingsActivity.this)
|
|
||||||
.getAccountsByType(Constants.ACCOUNT_TYPE);
|
|
||||||
final String[] choices = new String[accounts.length];
|
|
||||||
for (int i = 0; i < accounts.length; i++) {
|
|
||||||
choices[i] = accounts[i].name;
|
|
||||||
}
|
|
||||||
dialog = new AlertDialog.Builder(this).setNegativeButton(R.string.generic_cancel, null)
|
|
||||||
.setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialogInterface, int which) {
|
|
||||||
int position = ((AlertDialog) dialogInterface).getListView()
|
|
||||||
.getCheckedItemPosition();
|
|
||||||
PreferencesUtils.setString(
|
|
||||||
SettingsActivity.this, R.string.google_account_key, choices[position]);
|
|
||||||
dismissDialog(DIALOG_CHOOSE_ACCOUNT);
|
|
||||||
showDialog(DIALOG_CONFIRM_DRIVE_SYNC_ON);
|
|
||||||
}
|
|
||||||
}).setSingleChoiceItems(choices, 0, null)
|
|
||||||
.setTitle(R.string.send_google_choose_account_title).create();
|
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShow(DialogInterface dialogInterface) {
|
|
||||||
DialogUtils.setDialogTitleDivider(SettingsActivity.this, dialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case DIALOG_CONFIRM_DRIVE_SYNC_ON:
|
|
||||||
dialog = DialogUtils.createConfirmationDialog(this, R.string.sync_drive_confirm_title,
|
|
||||||
getString(R.string.sync_drive_confirm_message), new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface d, int button) {
|
|
||||||
if (syncDriveAsyncTask == null) {
|
|
||||||
String googleAccount = PreferencesUtils.getString(SettingsActivity.this,
|
|
||||||
R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
|
||||||
syncDriveAsyncTask = new CheckPermissionAsyncTask(
|
|
||||||
SettingsActivity.this, googleAccount, SendToGoogleUtils.DRIVE_SCOPE);
|
|
||||||
syncDriveAsyncTask.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
@@ -208,22 +163,6 @@ public class SettingsActivity extends AbstractSettingsActivity implements CheckP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
switch (requestCode) {
|
|
||||||
case DRIVE_REQUEST_CODE:
|
|
||||||
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
onDrivePermissionSuccess();
|
|
||||||
} else {
|
|
||||||
onDrivePermissionFailure();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrivePermissionSuccess() {
|
private void onDrivePermissionSuccess() {
|
||||||
handleSync(true);
|
handleSync(true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user