mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-03 18:03:06 +02:00
Removed Accounts and sync.
This commit is contained in:
@@ -22,38 +22,17 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile project(':myTracksLib')
|
||||
//compile files('libs/android-support-v4.jar')
|
||||
compile files('libs/antlib.jar')
|
||||
//compile files('libs/gdata-client-1.0.jar')
|
||||
//compile files('libs/gdata-client-meta-1.0.jar')
|
||||
//compile files('libs/gdata-core-1.0.jar')
|
||||
//compile files('libs/gdata-spreadsheet-3.0.jar')
|
||||
//compile files('libs/gdata-spreadsheet-meta-3.0.jar')
|
||||
compile files('libs/google-api-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar')
|
||||
//compile files('libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar')
|
||||
//compile files('libs/google-common.jar')
|
||||
compile files('libs/google-http-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-gson-1.12.0-beta.jar')
|
||||
//compile files('libs/google-http-client-jackson-1.12.0-beta.jar')
|
||||
//compile files('libs/google-http-client-jackson2-1.12.0-beta.jar')
|
||||
//compile files('libs/google-oauth-client-1.12.0-beta.jar')
|
||||
//compile files('libs/google-play-services.jar')
|
||||
//compile files('libs/gson-2.1.jar')
|
||||
compile files('libs/guava-jdk5-13.0.jar') //@visiblefortesting
|
||||
//compile files('libs/jackson-core-2.0.5.jar')
|
||||
//compile files('libs/jackson-core-asl-1.9.9.jar')
|
||||
//compile files('libs/jsr305.jar')
|
||||
//compile files('libs/libGoogleAnalytics.jar')
|
||||
androidTestCompile files('libs/AndroidMockGenerator.jar')
|
||||
androidTestCompile files('libs/robotium-solo-5.0.1.jar')
|
||||
|
||||
implementation 'com.google.android.gms:play-services-location:11.8.0'
|
||||
implementation 'com.google.android.gms:play-services:11.8.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:11.8.0'
|
||||
// compile 'com.google.firebase:firebase-core:9.2.0'
|
||||
// compile 'com.google.firebase:firebase-auth:9.2.0'
|
||||
// compile 'com.google.firebase:firebase-messaging:11.8.0'
|
||||
}
|
||||
|
||||
-85
@@ -1,85 +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.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 SendFusionTablesActivity}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SendFusionTablesActivityTest extends AndroidTestCase {
|
||||
|
||||
private SendFusionTablesActivity sendFusionTablesActivity;
|
||||
private SendRequest sendRequest;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
sendRequest = new SendRequest(1L);
|
||||
sendFusionTablesActivity = new SendFusionTablesActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to false and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelNotSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(false);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to true and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(SendSpreadsheetsActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to true and true.
|
||||
*/
|
||||
public void testGetNextClass_cancelSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to false and true.
|
||||
*/
|
||||
public void testGetNextClass_cancelNotSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(false);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
}
|
||||
-212
@@ -1,212 +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 android.location.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SendFusionTablesUtilsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null track.
|
||||
*/
|
||||
public void testGetMapUrl_null_track() {
|
||||
assertEquals(null, SendFusionTablesUtils.getMapUrl(null, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null stats.
|
||||
*/
|
||||
public void testGetMapUrl_null_stats() {
|
||||
Track track = new Track();
|
||||
track.setTripStatistics(null);
|
||||
assertEquals(null, SendFusionTablesUtils.getMapUrl(track, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with a valid track.
|
||||
*/
|
||||
public void testGetMapUrl_valid_track() {
|
||||
Track track = new Track();
|
||||
track.setNumberOfPoints(2);
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
|
||||
track.setTripStatistics(stats);
|
||||
assertEquals(
|
||||
"https://www.google.com/fusiontables/embedviz?"
|
||||
+ "viz=MAP&q=select+col0,+col1,+col2,+col3+from+123+&h=false&lat=7.500000&lng=75.000000"
|
||||
+ "&z=15&t=1&l=col2", SendFusionTablesUtils.getMapUrl(track, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* no value.
|
||||
*/
|
||||
public void testFormatSqlValues_no_value() {
|
||||
assertEquals("()", SendFusionTablesUtils.formatSqlValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* an empty string.
|
||||
*/
|
||||
public void testFormatSqlValues_empty_string() {
|
||||
assertEquals("(\'\')", SendFusionTablesUtils.formatSqlValues(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* one value.
|
||||
*/
|
||||
public void testFormatSqlValues_one_value() {
|
||||
assertEquals("(\'first\')", SendFusionTablesUtils.formatSqlValues("first"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* two values.
|
||||
*/
|
||||
public void testFormatSqlValues_two_values() {
|
||||
assertEquals(
|
||||
"(\'first\',\'second\')", SendFusionTablesUtils.formatSqlValues("first", "second"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#escapeSqlString(String)} with a value
|
||||
* containing several single quotes.
|
||||
*/
|
||||
public void testEscapeSqValuel() {
|
||||
String value = "let's'";
|
||||
assertEquals("let''s''", SendFusionTablesUtils.escapeSqlString(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a null
|
||||
* point.
|
||||
*/
|
||||
public void testGetKmlPoint_null_point() {
|
||||
assertEquals(
|
||||
"<Point><coordinates></coordinates></Point>", SendFusionTablesUtils.getKmlPoint(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a valid
|
||||
* point.
|
||||
*/
|
||||
public void testGetKmlPoint_valid_point() {
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
assertEquals("<Point><coordinates>10.1,20.2,30.3</coordinates></Point>",
|
||||
SendFusionTablesUtils.getKmlPoint(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with a null
|
||||
* locations.
|
||||
*/
|
||||
public void testKmlLineString_null_locations() {
|
||||
assertEquals("<LineString><coordinates></coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with no
|
||||
* location.
|
||||
*/
|
||||
public void testKmlLineString_no_location() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
assertEquals("<LineString><coordinates></coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with one
|
||||
* location.
|
||||
*/
|
||||
public void testKmlLineString_one_location() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
locations.add(location);
|
||||
assertEquals("<LineString><coordinates>10.1,20.2,30.3</coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with two
|
||||
* locations.
|
||||
*/
|
||||
public void testKmlLineString_two_locations() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location1 = new Location("test");
|
||||
location1.setLongitude(10.1);
|
||||
location1.setLatitude(20.2);
|
||||
location1.setAltitude(30.3);
|
||||
locations.add(location1);
|
||||
|
||||
Location location2 = new Location("test");
|
||||
location2.setLongitude(1.1);
|
||||
location2.setLatitude(2.2);
|
||||
location2.removeAltitude();
|
||||
locations.add(location2);
|
||||
|
||||
assertEquals("<LineString><coordinates>10.1,20.2,30.3 1.1,2.2</coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)}
|
||||
* with no altitude.
|
||||
*/
|
||||
public void testAppendLocation_no_altitude() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.removeAltitude();
|
||||
SendFusionTablesUtils.appendLocation(location, builder);
|
||||
assertEquals("10.1,20.2", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)}
|
||||
* with altitude.
|
||||
*/
|
||||
public void testAppendLocation_has_altitude() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
SendFusionTablesUtils.appendLocation(location, builder);
|
||||
assertEquals("10.1,20.2,30.3", builder.toString());
|
||||
}
|
||||
}
|
||||
@@ -156,10 +156,7 @@ limitations under the License.
|
||||
android:label="@string/menu_aggregated_statistics"
|
||||
android:name="com.google.android.apps.mytracks.AggregatedStatsActivity" />
|
||||
<activity android:name="com.google.android.apps.mytracks.DeleteActivity" />
|
||||
<activity
|
||||
android:label="@string/menu_help"
|
||||
android:name="com.google.android.apps.mytracks.HelpActivity" />
|
||||
<activity android:name="com.google.android.apps.mytracks.io.file.importer.ImportActivity" >
|
||||
<activity android:name="com.google.android.apps.mytracks.io.file.importer.ImportActivity" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ATTACH_DATA" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@@ -231,17 +228,6 @@ limitations under the License.
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Services -->
|
||||
<service
|
||||
android:exported="true"
|
||||
android:name="com.google.android.apps.mytracks.io.sync.SyncService" >
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.content.SyncAdapter"
|
||||
android:resource="@xml/sync_adapter" />
|
||||
</service>
|
||||
<service
|
||||
android:name="com.google.android.apps.mytracks.services.ActivityRecognitionIntentService" />
|
||||
<service
|
||||
|
||||
+2
-71
@@ -18,22 +18,13 @@ package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.fragments.ConfirmDeleteDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller;
|
||||
import com.google.android.apps.mytracks.fragments.InstallEarthDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment.ShareTrackCaller;
|
||||
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.services.TrackRecordingServiceConnection;
|
||||
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
@@ -42,48 +33,16 @@ import android.widget.Toast;
|
||||
* {@link SearchListActivity}:
|
||||
* <p>
|
||||
* - share track <br>
|
||||
* - export track to Google services<br>
|
||||
* - enable sync to Google Drive <br>
|
||||
* - delete tracks <br>
|
||||
* - play tracks
|
||||
*
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity
|
||||
implements ShareTrackCaller, ConfirmDeleteCaller {
|
||||
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity implements ConfirmDeleteCaller {
|
||||
|
||||
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
|
||||
private static final String SEND_REQUEST_KEY = "send_request_key";
|
||||
private static final int DRIVE_REQUEST_CODE = 0;
|
||||
private static final int FUSION_TABLES_REQUEST_CODE = 1;
|
||||
private static final int SPREADSHEETS_REQUEST_CODE = 2;
|
||||
private static final int DELETE_REQUEST_CODE = 3;
|
||||
protected static final int GOOGLE_PLAY_SERVICES_REQUEST_CODE = 4;
|
||||
protected static final int CAMERA_REQUEST_CODE = 5;
|
||||
|
||||
private CheckPermissionAsyncTask asyncTask;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
//sendRequest = savedInstanceState.getParcelable(SEND_REQUEST_KEY);
|
||||
}
|
||||
Object retained = getLastCustomNonConfigurationInstance();
|
||||
if (retained instanceof CheckPermissionAsyncTask) {
|
||||
asyncTask = (CheckPermissionAsyncTask) retained;
|
||||
asyncTask.setActivity(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainCustomNonConfigurationInstance() {
|
||||
if (asyncTask != null) {
|
||||
asyncTask.setActivity(null);
|
||||
}
|
||||
return asyncTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
@@ -95,16 +54,6 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shares a track.
|
||||
*
|
||||
* @param trackId the track id
|
||||
*/
|
||||
protected void shareTrack(long trackId) {
|
||||
ShareTrackDialogFragment.newInstance(trackId)
|
||||
.show(getSupportFragmentManager(), ShareTrackDialogFragment.SHARE_TRACK_DIALOG_TAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when not able to get permission for a google service.
|
||||
*/
|
||||
@@ -155,22 +104,4 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
|
||||
* Called after {@link DeleteActivity} returns its result.
|
||||
*/
|
||||
abstract protected void onDeleted();
|
||||
|
||||
/**
|
||||
* Play tracks in Google Earth.
|
||||
*
|
||||
* @param trackIds the track ids
|
||||
*/
|
||||
protected void playTracks(long[] trackIds) {
|
||||
if (GoogleEarthUtils.isEarthInstalled(this)) {
|
||||
Intent intent = IntentUtils.newIntent(this, SaveActivity.class)
|
||||
.putExtra(SaveActivity.EXTRA_TRACK_IDS, trackIds)
|
||||
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) TrackFileFormat.KML)
|
||||
.putExtra(SaveActivity.EXTRA_PLAY_TRACK, true);
|
||||
startActivity(intent);
|
||||
} else {
|
||||
new InstallEarthDialogFragment().show(
|
||||
getSupportFragmentManager(), InstallEarthDialogFragment.INSTALL_EARTH_DIALOG_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
@@ -36,12 +27,21 @@ import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -16,16 +16,13 @@ package com.google.android.apps.mytracks;
|
||||
* the License.
|
||||
*/
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
|
||||
/**
|
||||
* Async Task to delete tracks.
|
||||
*
|
||||
@@ -81,40 +78,16 @@ public class DeleteAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
|
||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
||||
try {
|
||||
while (SyncUtils.isSyncActive(context)) {
|
||||
if (isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
Thread.sleep(ONE_SECOND);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
SyncUtils.disableSync(context);
|
||||
myTracksProviderUtils.deleteAllTracks(context);
|
||||
return true;
|
||||
} else {
|
||||
for (long id : trackIds) {
|
||||
if (isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
Track track = myTracksProviderUtils.getTrack(id);
|
||||
myTracksProviderUtils.deleteTrack(context, id);
|
||||
if (track != null) {
|
||||
String driveId = track.getDriveId();
|
||||
if (driveId != null && !driveId.equals("")) {
|
||||
boolean driveSync = PreferencesUtils.getBoolean(
|
||||
context, R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
if (driveSync) {
|
||||
PreferencesUtils.addToList(context, R.string.drive_deleted_list_key,
|
||||
PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT, driveId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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;
|
||||
|
||||
import com.google.android.apps.mytracks.fragments.EulaDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.EulaDialogFragment.EulaCaller;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.GoogleFeedbackUtils;
|
||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Button;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An activity that displays the help page.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class HelpActivity extends AbstractMyTracksActivity implements EulaCaller {
|
||||
|
||||
WebView webView;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String subtitle = getString(R.string.my_tracks_app_name) + " v"
|
||||
+ SystemUtils.getMyTracksVersion(this);
|
||||
ApiAdapterFactory.getApiAdapter()
|
||||
.setTitleAndSubtitle(this, getString(R.string.menu_help), subtitle);
|
||||
|
||||
webView = (WebView) findViewById(R.id.help_webview);
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new WebViewClient());
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
if (language == null || language.equals("")) {
|
||||
language = "en";
|
||||
}
|
||||
webView.loadUrl(getString(R.string.my_tracks_help_url, language));
|
||||
} else {
|
||||
webView.restoreState(savedInstanceState);
|
||||
}
|
||||
|
||||
Button feedback = (Button) findViewById(R.id.help_feedback);
|
||||
boolean showFeedback = ApiAdapterFactory.getApiAdapter().isGoogleFeedbackAvailable();
|
||||
feedback.setVisibility(showFeedback ? View.VISIBLE : View.GONE);
|
||||
if (showFeedback) {
|
||||
feedback.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
GoogleFeedbackUtils.bindFeedback(HelpActivity.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (webView != null) {
|
||||
webView.saveState(outState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.help;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.help, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Intent intent;
|
||||
switch (item.getItemId()) {
|
||||
case R.id.help_play_store:
|
||||
intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("market://details?id=com.google.android.maps.mytracks"));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.help_eula:
|
||||
EulaDialogFragment.newInstance(true)
|
||||
.show(getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG);
|
||||
return true;
|
||||
case R.id.help_forum:
|
||||
intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(
|
||||
"http://groups.google.com/a/googleproductforums.com/forum/#!categories/maps/mytracks/"));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEulaDone() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@@ -125,18 +125,6 @@ public class MarkerEditActivity extends AbstractMyTracksActivity {
|
||||
} else {
|
||||
saveMarker();
|
||||
}
|
||||
boolean driveSync = PreferencesUtils.getBoolean(
|
||||
MarkerEditActivity.this, R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
if (driveSync) {
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(
|
||||
MarkerEditActivity.this);
|
||||
Track track = myTracksProviderUtils.getTrack(newMarker ? trackId : waypoint.getTrackId());
|
||||
track.setModifiedTime(System.currentTimeMillis());
|
||||
myTracksProviderUtils.updateTrack(track);
|
||||
PreferencesUtils.addToList(MarkerEditActivity.this, R.string.drive_edited_list_key,
|
||||
PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT, String.valueOf(track.getId()));
|
||||
}
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -72,8 +72,6 @@ public class MarkerListActivity extends AbstractMyTracksActivity implements Dele
|
||||
public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
|
||||
boolean isSingleSelection = ids.length == 1;
|
||||
|
||||
// Always disable
|
||||
menu.findItem(R.id.list_context_menu_play).setVisible(false);
|
||||
// Always disable
|
||||
menu.findItem(R.id.list_context_menu_share).setVisible(false);
|
||||
// One item
|
||||
|
||||
@@ -149,9 +149,6 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
||||
isSingleSelectionShareWithMe = false;
|
||||
isSingleSelectionTrack = false;
|
||||
}
|
||||
// Not recording, one item, item is a track
|
||||
menu.findItem(R.id.list_context_menu_play)
|
||||
.setVisible(!isRecording && isSingleSelection && isSingleSelectionTrack);
|
||||
// Not recording, one item, item is a track, not shareWithMe item
|
||||
menu.findItem(R.id.list_context_menu_share).setVisible(!isRecording && isSingleSelection
|
||||
&& isSingleSelectionTrack && !isSingleSelectionShareWithMe);
|
||||
@@ -347,11 +344,9 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
||||
Intent intent;
|
||||
switch (itemId) {
|
||||
case R.id.list_context_menu_play:
|
||||
playTracks(new long[] {trackId});
|
||||
return true;
|
||||
case R.id.list_context_menu_share:
|
||||
shareTrack(trackId);
|
||||
//TODO
|
||||
Log.e(TAG, "Not implemented");
|
||||
return true;
|
||||
case R.id.list_context_menu_show_on_map:
|
||||
intent = IntentUtils.newIntent(this, TrackDetailActivity.class)
|
||||
@@ -557,9 +552,4 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@ import com.google.android.apps.mytracks.fragments.ExportDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ExportDialogFragment.ExportCaller;
|
||||
import com.google.android.apps.mytracks.fragments.ExportDialogFragment.ExportType;
|
||||
import com.google.android.apps.mytracks.fragments.FrequencyDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.MapLayerDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment.PlayMultipleCaller;
|
||||
import com.google.android.apps.mytracks.fragments.StatsFragment;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.io.file.exporter.SaveActivity;
|
||||
@@ -80,7 +77,7 @@ import java.util.Date;
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
implements ChooseActivityTypeCaller, ExportCaller, PlayMultipleCaller {
|
||||
implements ChooseActivityTypeCaller, ExportCaller {
|
||||
|
||||
public static final String EXTRA_TRACK_ID = "track_id";
|
||||
public static final String EXTRA_MARKER_ID = "marker_id";
|
||||
@@ -114,7 +111,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
|
||||
private MenuItem insertMarkerMenuItem;
|
||||
private MenuItem insertPhotoMenuItem;
|
||||
private MenuItem playMenuItem;
|
||||
private MenuItem shareMenuItem;
|
||||
private MenuItem exportMenuItem;
|
||||
private MenuItem voiceFrequencyMenuItem;
|
||||
@@ -357,7 +353,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
|
||||
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
|
||||
insertPhotoMenuItem = menu.findItem(R.id.track_detail_insert_photo);
|
||||
playMenuItem = menu.findItem(R.id.track_detail_play);
|
||||
|
||||
shareMenuItem = menu.findItem(R.id.track_detail_share);
|
||||
shareMenuItem.setEnabled(!isSharedWithMe);
|
||||
@@ -402,21 +397,11 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
MediaStore.EXTRA_OUTPUT, photoUri);
|
||||
startActivityForResult(intent, CAMERA_REQUEST_CODE);
|
||||
return true;
|
||||
case R.id.track_detail_play:
|
||||
playTracks(new long[] {trackId});
|
||||
return true;
|
||||
case R.id.track_detail_share:
|
||||
shareTrack(trackId);
|
||||
return true;
|
||||
case R.id.track_detail_markers:
|
||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
||||
.putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_detail_play_multiple:
|
||||
PlayMultipleDialogFragment.newInstance(trackId)
|
||||
.show(getSupportFragmentManager(), PlayMultipleDialogFragment.PLAY_MULTIPLE_DIALOG_TAG);
|
||||
return true;
|
||||
case R.id.track_detail_voice_frequency:
|
||||
FrequencyDialogFragment.newInstance(R.string.voice_frequency_key,
|
||||
PreferencesUtils.VOICE_FREQUENCY_DEFAULT, R.string.menu_voice_frequency)
|
||||
@@ -449,10 +434,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
intent = IntentUtils.newIntent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_detail_help_feedback:
|
||||
intent = IntentUtils.newIntent(this, HelpActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -470,7 +451,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
return super.onTrackballEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExportDone(
|
||||
ExportType exportType, TrackFileFormat trackFileFormat, Account account) {
|
||||
if (exportType == ExportType.EXTERNAL_STORAGE) {
|
||||
@@ -563,9 +543,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
if (insertPhotoMenuItem != null) {
|
||||
insertPhotoMenuItem.setVisible(hasCamera && isRecording && !isPaused);
|
||||
}
|
||||
if (playMenuItem != null) {
|
||||
playMenuItem.setVisible(!isRecording);
|
||||
}
|
||||
if (shareMenuItem != null && shareMenuItem.isEnabled()) {
|
||||
shareMenuItem.setVisible(!isRecording);
|
||||
}
|
||||
@@ -610,22 +587,9 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPlayMultipleDone(long[] trackIds) {
|
||||
playTracks(trackIds);
|
||||
public void onExportDone(ExportType exportType, TrackFileFormat trackFileFormat) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the map layer dialog.
|
||||
*/
|
||||
public void showMapLayerDialog() {
|
||||
new MapLayerDialogFragment().show(
|
||||
getSupportFragmentManager(), MapLayerDialogFragment.MAP_LAYER_DIALOG_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -18,24 +18,14 @@ package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragment;
|
||||
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.EnableSyncCaller;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
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.CheckPermissionCaller;
|
||||
import com.google.android.apps.mytracks.util.EulaUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@@ -48,7 +38,6 @@ import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* An activity that let's the user see and edit the user editable track meta
|
||||
@@ -56,8 +45,7 @@ import android.widget.Toast;
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class TrackEditActivity extends AbstractMyTracksActivity implements ChooseActivityTypeCaller,
|
||||
EnableSyncCaller, ChooseAccountCaller, CheckPermissionCaller {
|
||||
public class TrackEditActivity extends AbstractMyTracksActivity implements ChooseActivityTypeCaller {
|
||||
|
||||
public static final String EXTRA_TRACK_ID = "track_id";
|
||||
public static final String EXTRA_NEW_TRACK = "new_track";
|
||||
@@ -80,18 +68,10 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
||||
|
||||
private boolean newWeight = false;
|
||||
|
||||
private CheckPermissionAsyncTask syncDriveAsyncTask;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
Object retained = getLastCustomNonConfigurationInstance();
|
||||
if (retained instanceof CheckPermissionAsyncTask) {
|
||||
syncDriveAsyncTask = (CheckPermissionAsyncTask) retained;
|
||||
syncDriveAsyncTask.setActivity(this);
|
||||
}
|
||||
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null);
|
||||
trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
if (trackId == -1L) {
|
||||
@@ -177,19 +157,6 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
||||
TrackUtils.updateTrack(TrackEditActivity.this, track, name.getText().toString(),
|
||||
activityType.getText().toString(), description.getText().toString(),
|
||||
myTracksProviderUtils, trackRecordingServiceConnection, newWeight);
|
||||
|
||||
if (EulaUtils.showEnableSync(TrackEditActivity.this)) {
|
||||
EulaUtils.setShowEnableSync(TrackEditActivity.this);
|
||||
if (PreferencesUtils.getBoolean(TrackEditActivity.this, R.string.drive_sync_key,
|
||||
PreferencesUtils.DRIVE_SYNC_DEFAULT)) {
|
||||
finish();
|
||||
} else {
|
||||
new EnableSyncDialogFragment().show(
|
||||
getSupportFragmentManager(), EnableSyncDialogFragment.ENABLE_SYNC_DIALOG_TAG);
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -209,13 +176,6 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainCustomNonConfigurationInstance() {
|
||||
if (syncDriveAsyncTask != null) {
|
||||
syncDriveAsyncTask.setActivity(null);
|
||||
}
|
||||
return syncDriveAsyncTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
@@ -253,24 +213,4 @@ public class TrackEditActivity extends AbstractMyTracksActivity implements Choos
|
||||
setActivityTypeIcon(value);
|
||||
activityType.setText(getString(TrackIconUtils.getIconActivityType(value)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableSyncDone(boolean enable) {
|
||||
if (enable) {
|
||||
new ChooseAccountDialogFragment().show(
|
||||
getSupportFragmentManager(), ChooseAccountDialogFragment.CHOOSE_ACCOUNT_DIALOG_TAG);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChooseAccountDone(String account) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,42 +16,6 @@
|
||||
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller;
|
||||
import com.google.android.apps.mytracks.fragments.ConfirmSyncDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ConfirmSyncDialogFragment.ConfirmSyncCaller;
|
||||
import com.google.android.apps.mytracks.fragments.EulaDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.EulaDialogFragment.EulaCaller;
|
||||
import com.google.android.apps.mytracks.fragments.FileTypeDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.FileTypeDialogFragment.FileTypeCaller;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment.PlayMultipleCaller;
|
||||
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.importer.ImportActivity;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
||||
import com.google.android.apps.mytracks.services.MyTracksLocationManager;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||
import com.google.android.apps.mytracks.settings.SettingsActivity;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.EulaUtils;
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.ListItemUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackUtils;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.maps.mytracks.BuildConfig;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Dialog;
|
||||
import android.app.SearchManager;
|
||||
@@ -65,7 +29,6 @@ import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
@@ -84,6 +47,32 @@ import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.fragments.FileTypeDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.FileTypeDialogFragment.FileTypeCaller;
|
||||
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.importer.ImportActivity;
|
||||
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
||||
import com.google.android.apps.mytracks.services.MyTracksLocationManager;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||
import com.google.android.apps.mytracks.settings.SettingsActivity;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.ListItemUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackUtils;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.maps.mytracks.BuildConfig;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -91,8 +80,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
implements EulaCaller, FileTypeCaller, PlayMultipleCaller, ChooseAccountCaller, ConfirmSyncCaller {
|
||||
public class TrackListActivity extends AbstractSendToGoogleActivity implements FileTypeCaller {
|
||||
|
||||
private static final String TAG = TrackListActivity.class.getSimpleName();
|
||||
private static final String[] PROJECTION = new String[] { TracksColumns._ID, TracksColumns.NAME,
|
||||
@@ -181,11 +169,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
R.string.recording_track_paused_key,
|
||||
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
|
||||
}
|
||||
if (key == null || key.equals(
|
||||
PreferencesUtils.getKey(TrackListActivity.this, R.string.drive_sync_key))) {
|
||||
driveSync = PreferencesUtils.getBoolean(TrackListActivity.this, R.string.drive_sync_key,
|
||||
PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
}
|
||||
if (key != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -217,8 +200,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
isSingleSelectionShareWithMe = false;
|
||||
}
|
||||
|
||||
// Not recording
|
||||
menu.findItem(R.id.list_context_menu_play).setVisible(!isRecording);
|
||||
// Not recording, one item, not sharedWithMe item
|
||||
menu.findItem(R.id.list_context_menu_share)
|
||||
.setVisible(!isRecording && isSingleSelection && !isSingleSelectionShareWithMe);
|
||||
@@ -298,13 +279,10 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
private boolean metricUnits = true;
|
||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||
private boolean recordingTrackPaused = PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT;
|
||||
private boolean driveSync = PreferencesUtils.DRIVE_SYNC_DEFAULT;
|
||||
|
||||
// Menu items
|
||||
private MenuItem searchMenuItem;
|
||||
private MenuItem startGpsMenuItem;
|
||||
private MenuItem playMultipleItem;
|
||||
private MenuItem syncNowMenuItem;
|
||||
private MenuItem aggregatedStatisticsMenuItem;
|
||||
private MenuItem exportAllMenuItem;
|
||||
private MenuItem importAllMenuItem;
|
||||
@@ -456,16 +434,10 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.track_list, menu);
|
||||
|
||||
menu.findItem(R.id.track_list_help_feedback).setTitle(
|
||||
ApiAdapterFactory.getApiAdapter().isGoogleFeedbackAvailable() ? R.string.menu_help_feedback
|
||||
: R.string.menu_help);
|
||||
|
||||
searchMenuItem = menu.findItem(R.id.track_list_search);
|
||||
ApiAdapterFactory.getApiAdapter().configureSearchWidget(this, searchMenuItem, trackController);
|
||||
|
||||
startGpsMenuItem = menu.findItem(R.id.track_list_start_gps);
|
||||
playMultipleItem = menu.findItem(R.id.track_list_play_mutliple);
|
||||
syncNowMenuItem = menu.findItem(R.id.track_list_sync_now);
|
||||
aggregatedStatisticsMenuItem = menu.findItem(R.id.track_list_aggregated_statistics);
|
||||
exportAllMenuItem = menu.findItem(R.id.track_list_export_all);
|
||||
importAllMenuItem = menu.findItem(R.id.track_list_import_all);
|
||||
@@ -526,18 +498,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
}
|
||||
myTracksLocationManager.close();
|
||||
return true;
|
||||
case R.id.track_list_play_mutliple:
|
||||
PlayMultipleDialogFragment.newInstance(-1L)
|
||||
.show(getSupportFragmentManager(), PlayMultipleDialogFragment.PLAY_MULTIPLE_DIALOG_TAG);
|
||||
return true;
|
||||
case R.id.track_list_sync_now:
|
||||
if (driveSync) {
|
||||
SyncUtils.syncNow(this);
|
||||
} else {
|
||||
new ChooseAccountDialogFragment().show(
|
||||
getSupportFragmentManager(), ChooseAccountDialogFragment.CHOOSE_ACCOUNT_DIALOG_TAG);
|
||||
}
|
||||
return true;
|
||||
case R.id.track_list_aggregated_statistics:
|
||||
intent = IntentUtils.newIntent(this, AggregatedStatsActivity.class);
|
||||
startActivity(intent);
|
||||
@@ -559,10 +519,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
intent = IntentUtils.newIntent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_list_help_feedback:
|
||||
intent = IntentUtils.newIntent(this, HelpActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -638,14 +594,7 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
* Shows start up dialogs.
|
||||
*/
|
||||
public void showStartupDialogs() {
|
||||
if (!EulaUtils.hasAcceptedEula(this)) {
|
||||
Fragment fragment = getSupportFragmentManager()
|
||||
.findFragmentByTag(EulaDialogFragment.EULA_DIALOG_TAG);
|
||||
if (fragment == null) {
|
||||
EulaDialogFragment.newInstance(false)
|
||||
.show(getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
// If stats_units_key is undefined, set it
|
||||
if (PreferencesUtils.getString(this, R.string.stats_units_key, "").equals("")) {
|
||||
String statsUnits = getString(
|
||||
@@ -657,15 +606,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEulaDone() {
|
||||
if (EulaUtils.hasAcceptedEula(this)) {
|
||||
showStartupDialogs();
|
||||
return;
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
private void checkGooglePlayServices() {
|
||||
int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
|
||||
if (code != ConnectionResult.SUCCESS) {
|
||||
@@ -701,12 +641,6 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
TrackIconUtils.setMenuIconColor(startGpsMenuItem);
|
||||
}
|
||||
}
|
||||
if (playMultipleItem != null) {
|
||||
playMultipleItem.setVisible(hasTrack);
|
||||
}
|
||||
if (syncNowMenuItem != null) {
|
||||
syncNowMenuItem.setTitle(driveSync ? R.string.menu_sync_now : R.string.menu_sync_drive);
|
||||
}
|
||||
if (aggregatedStatisticsMenuItem != null) {
|
||||
aggregatedStatisticsMenuItem.setVisible(hasTrack);
|
||||
}
|
||||
@@ -746,11 +680,9 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
*/
|
||||
private boolean handleContextItem(int itemId, long[] trackIds) {
|
||||
switch (itemId) {
|
||||
case R.id.list_context_menu_play:
|
||||
playTracks(trackIds);
|
||||
return true;
|
||||
case R.id.list_context_menu_share:
|
||||
shareTrack(trackIds[0]);
|
||||
//TODO
|
||||
Log.e(TAG, "Not implemented");
|
||||
return true;
|
||||
case R.id.list_context_menu_edit:
|
||||
Intent intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
||||
@@ -769,38 +701,7 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
||||
listView.setItemChecked(i, true);
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayMultipleDone(long[] trackIds) {
|
||||
playTracks(trackIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChooseAccountDone(String account) {
|
||||
PreferencesUtils.setString(this, R.string.google_account_key, account);
|
||||
if (PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT.equals(account)) {
|
||||
return;
|
||||
} else {
|
||||
new ConfirmSyncDialogFragment().show(
|
||||
getSupportFragmentManager(), ConfirmSyncDialogFragment.CONFIRM_SYNC_DIALOG_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmSyncDone(boolean enable) {
|
||||
if (enable) {
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
this, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
//enableSync(new Account(googleAccount, Constants.ACCOUNT_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,14 +16,14 @@
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.ChartURLGenerator;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
+6
-5
@@ -16,11 +16,6 @@
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
@@ -37,9 +32,14 @@ import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Process;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
@@ -52,6 +52,7 @@ import java.io.FileNotFoundException;
|
||||
public class MyTracksProvider extends ContentProvider {
|
||||
|
||||
private static final String TAG = MyTracksProvider.class.getSimpleName();
|
||||
|
||||
@VisibleForTesting
|
||||
static final int DATABASE_VERSION = 22;
|
||||
|
||||
|
||||
@@ -16,19 +16,19 @@
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
+11
-11
@@ -16,6 +16,17 @@
|
||||
|
||||
package com.google.android.apps.mytracks.fragments;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.ZoomControls;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView;
|
||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
@@ -33,17 +44,6 @@ import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.ZoomControls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
-123
@@ -1,123 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* A DialogFragment to choose an account.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class ChooseAccountDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
/**
|
||||
* Interface for caller of this dialog fragment.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface ChooseAccountCaller {
|
||||
|
||||
/**
|
||||
* Called when choose account is done.
|
||||
*
|
||||
* @param account the account chosen
|
||||
*/
|
||||
public void onChooseAccountDone(String account);
|
||||
}
|
||||
|
||||
public static final String CHOOSE_ACCOUNT_DIALOG_TAG = "chooseAccount";
|
||||
|
||||
private ChooseAccountCaller caller;
|
||||
private Account[] accounts;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
caller = (ChooseAccountCaller) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(
|
||||
activity.toString() + " must implement " + ChooseAccountCaller.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
FragmentActivity fragmentActivity = getActivity();
|
||||
accounts = AccountManager.get(fragmentActivity).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
|
||||
if (accounts.length == 1) {
|
||||
dismiss();
|
||||
caller.onChooseAccountDone(accounts[0].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
if (accounts.length == 0) {
|
||||
return new AlertDialog.Builder(getActivity()).setMessage(
|
||||
R.string.send_google_no_account_message).setTitle(R.string.send_google_no_account_title)
|
||||
.setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
caller.onChooseAccountDone(PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
String[] choices = new String[accounts.length];
|
||||
for (int i = 0; i < accounts.length; i++) {
|
||||
choices[i] = accounts[i].name;
|
||||
}
|
||||
return new AlertDialog.Builder(getActivity()).setNegativeButton(
|
||||
R.string.generic_cancel, new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
caller.onChooseAccountDone(PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
|
||||
}
|
||||
}).setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
|
||||
caller.onChooseAccountDone(accounts[position].name);
|
||||
}
|
||||
}).setSingleChoiceItems(choices, 0, null).setTitle(R.string.send_google_choose_account_title)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
caller.onChooseAccountDone(PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
}
|
||||
}
|
||||
+4
-12
@@ -84,18 +84,10 @@ public class ConfirmDeleteDialogFragment extends AbstractMyTracksDialogFragment
|
||||
final long[] trackIds = getArguments().getLongArray(KEY_TRACK_IDS);
|
||||
int titleId;
|
||||
int messageId;
|
||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
||||
boolean driveSync = PreferencesUtils.getBoolean(
|
||||
getActivity(), R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
titleId = R.string.generic_delete_all_confirm_title;
|
||||
messageId = driveSync ? R.string.track_delete_all_confirm_message_sync_on
|
||||
: R.string.track_delete_all_confirm_message_sync_off;
|
||||
} else {
|
||||
titleId = trackIds.length > 1 ? R.string.generic_delete_selected_confirm_title
|
||||
: R.string.track_delete_one_confirm_title;
|
||||
messageId = trackIds.length > 1 ? R.string.track_delete_multiple_confirm_message
|
||||
: R.string.track_delete_one_confirm_message;
|
||||
}
|
||||
titleId = trackIds.length > 1 ? R.string.generic_delete_selected_confirm_title
|
||||
: R.string.track_delete_one_confirm_title;
|
||||
messageId = trackIds.length > 1 ? R.string.track_delete_multiple_confirm_message
|
||||
: R.string.track_delete_one_confirm_message;
|
||||
return DialogUtils.createConfirmationDialog(
|
||||
getActivity(), titleId, getString(messageId), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
|
||||
-89
@@ -1,89 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* A DialogFrament to confirm sync to Google Drive.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class ConfirmSyncDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
/**
|
||||
* Interface for caller of this dialog fragment.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface ConfirmSyncCaller {
|
||||
|
||||
/**
|
||||
* Called when confirm sync is done.
|
||||
*/
|
||||
public void onConfirmSyncDone(boolean enable);
|
||||
}
|
||||
|
||||
public static final String CONFIRM_SYNC_DIALOG_TAG = "confirmSyncDialog";
|
||||
|
||||
private ConfirmSyncCaller caller;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
caller = (ConfirmSyncCaller) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(
|
||||
activity.toString() + " must implement " + ConfirmSyncCaller.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
FragmentActivity fragmentActivity = getActivity();
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
fragmentActivity, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
String message = getString(
|
||||
R.string.sync_drive_confirm_message, googleAccount, getString(R.string.my_tracks_app_name));
|
||||
return new AlertDialog.Builder(fragmentActivity).setMessage(message)
|
||||
.setNegativeButton(R.string.generic_no, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
caller.onConfirmSyncDone(false);
|
||||
}
|
||||
}).setPositiveButton(R.string.generic_yes, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
caller.onConfirmSyncDone(true);
|
||||
}
|
||||
}).setTitle(R.string.sync_drive_confirm_title).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface arg0) {
|
||||
caller.onConfirmSyncDone(false);
|
||||
}
|
||||
}
|
||||
-148
@@ -1,148 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.EulaUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* A DialogFragment to show EULA.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class EulaDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
/**
|
||||
* Interface for caller of this dialog fragment.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface EulaCaller {
|
||||
|
||||
/**
|
||||
* Called when eula is done.
|
||||
*/
|
||||
public void onEulaDone();
|
||||
}
|
||||
|
||||
public static final String EULA_DIALOG_TAG = "eulaDialog";
|
||||
private static final String KEY_HAS_ACCEPTED = "hasAccepted";
|
||||
private static final String GOOGLE_URL = "m.google.com";
|
||||
private static final String KOREAN = "ko";
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link EulaDialogFragment}.
|
||||
*
|
||||
* @param hasAccepted true if the user has accepted the eula.
|
||||
*/
|
||||
public static EulaDialogFragment newInstance(boolean hasAccepted) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_HAS_ACCEPTED, hasAccepted);
|
||||
|
||||
EulaDialogFragment eulaDialogFragment = new EulaDialogFragment();
|
||||
eulaDialogFragment.setArguments(bundle);
|
||||
return eulaDialogFragment;
|
||||
}
|
||||
|
||||
private EulaCaller caller;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
caller = (EulaCaller) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(
|
||||
activity.toString() + " must implement " + EulaCaller.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
boolean hasAccepted = getArguments().getBoolean(KEY_HAS_ACCEPTED);
|
||||
|
||||
SpannableString message = new SpannableString(getEulaText());
|
||||
Linkify.addLinks(message, Linkify.WEB_URLS);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setMessage(message)
|
||||
.setTitle(R.string.menu_help_eula);
|
||||
|
||||
if (hasAccepted) {
|
||||
builder.setPositiveButton(R.string.generic_ok, null);
|
||||
} else {
|
||||
builder.setNegativeButton(R.string.eula_decline, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
caller.onEulaDone();
|
||||
}
|
||||
}).setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}).setPositiveButton(R.string.eula_accept, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
EulaUtils.setAcceptedEula(getActivity());
|
||||
caller.onEulaDone();
|
||||
}
|
||||
});
|
||||
}
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
TextView textView = (TextView) getDialog().findViewById(android.R.id.message);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
textView.setTextAppearance(getActivity(), R.style.TextSmall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface arg0) {
|
||||
caller.onEulaDone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EULA text.
|
||||
*/
|
||||
private String getEulaText() {
|
||||
String tos = getString(R.string.eula_date) + "\n\n" + getString(R.string.eula_body, GOOGLE_URL)
|
||||
+ "\n\n" + getString(R.string.eula_footer, GOOGLE_URL) + "\n\n"
|
||||
+ getString(R.string.eula_copyright_year);
|
||||
boolean isKorean = getResources().getConfiguration().locale.getLanguage().equals(KOREAN);
|
||||
if (isKorean) {
|
||||
tos += "\n\n" + getString(R.string.eula_korean);
|
||||
}
|
||||
return tos;
|
||||
}
|
||||
}
|
||||
+22
-136
@@ -18,7 +18,6 @@ package com.google.android.apps.mytracks.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.AccountUtils;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
@@ -53,10 +52,6 @@ public class ExportDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public enum ExportType {
|
||||
GOOGLE_DRIVE(R.string.export_google_drive),
|
||||
GOOGLE_MAPS(R.string.export_google_maps),
|
||||
GOOGLE_FUSION_TABLES(R.string.export_google_fusion_tables),
|
||||
GOOGLE_SPREADSHEET(R.string.export_google_spreadsheets),
|
||||
EXTERNAL_STORAGE(R.string.export_external_storage);
|
||||
final int resId;
|
||||
|
||||
@@ -77,35 +72,24 @@ public class ExportDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
*
|
||||
* @param exportType the export type
|
||||
* @param trackFileFormat the track file format
|
||||
* @param account the account
|
||||
*/
|
||||
public void onExportDone(
|
||||
ExportType exportType, TrackFileFormat trackFileFormat, Account account);
|
||||
ExportType exportType, TrackFileFormat trackFileFormat);
|
||||
}
|
||||
|
||||
public static final String EXPORT_DIALOG_TAG = "export";
|
||||
|
||||
private static final String KEY_HIDE_DRIVE = "hideDrive";
|
||||
|
||||
public static ExportDialogFragment newInstance(boolean hideDrive) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_HIDE_DRIVE, hideDrive);
|
||||
|
||||
ExportDialogFragment fragment = new ExportDialogFragment();
|
||||
fragment.setArguments(bundle);
|
||||
return fragment;
|
||||
//TODO REMOVE
|
||||
return new ExportDialogFragment();
|
||||
}
|
||||
|
||||
private ExportCaller caller;
|
||||
private Account[] accounts;
|
||||
private ArrayList<ExportType> exportTypeOptionsList;
|
||||
|
||||
// UI elements
|
||||
private Spinner exportTypeOptions;
|
||||
private RadioGroup exportGoogleMapsOptions;
|
||||
private RadioGroup exportGoogleFusionTablesOptions;
|
||||
private RadioGroup exportExternalStorageOptions;
|
||||
private Spinner accountSpinner;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
@@ -121,34 +105,10 @@ public class ExportDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
FragmentActivity fragmentActivity = getActivity();
|
||||
accounts = AccountManager.get(fragmentActivity).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
|
||||
// Get views
|
||||
View view = fragmentActivity.getLayoutInflater().inflate(R.layout.export, null);
|
||||
exportTypeOptions = (Spinner) view.findViewById(R.id.export_type_options);
|
||||
exportGoogleMapsOptions = (RadioGroup) view.findViewById(R.id.export_google_maps_options);
|
||||
exportGoogleFusionTablesOptions = (RadioGroup) view.findViewById(
|
||||
R.id.export_google_fusion_tables_options);
|
||||
exportExternalStorageOptions = (RadioGroup) view.findViewById(
|
||||
R.id.export_external_storage_options);
|
||||
accountSpinner = (Spinner) view.findViewById(R.id.export_account);
|
||||
|
||||
// Setup exportTypeOptions
|
||||
setupExportTypeOptions(fragmentActivity);
|
||||
|
||||
// Setup exportGoogleMapsOptions
|
||||
boolean exportGoogleMapsPublic = PreferencesUtils.getBoolean(fragmentActivity,
|
||||
R.string.export_google_maps_public_key, PreferencesUtils.EXPORT_GOOGLE_MAPS_PUBLIC_DEFAULT);
|
||||
exportGoogleMapsOptions.check(
|
||||
exportGoogleMapsPublic ? R.id.export_google_maps_public : R.id.export_google_maps_unlisted);
|
||||
|
||||
// Setup exportGoogleFusionTablesOptions
|
||||
boolean exportGoogleFusionTablesPublic = PreferencesUtils.getBoolean(fragmentActivity,
|
||||
R.string.export_google_fusion_tables_public_key,
|
||||
PreferencesUtils.EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT);
|
||||
exportGoogleFusionTablesOptions.check(
|
||||
exportGoogleFusionTablesPublic ? R.id.export_google_fusion_tables_public
|
||||
: R.id.export_google_fusion_tables_private);
|
||||
|
||||
// Setup exportExternalStorageOptions
|
||||
setExternalStorageOption(
|
||||
@@ -164,100 +124,26 @@ public class ExportDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
PreferencesUtils.EXPORT_EXTERNAL_STORAGE_FORMAT_DEFAULT));
|
||||
exportExternalStorageOptions.check(getExternalStorageFormatId(trackFileFormat));
|
||||
|
||||
// Setup accountSpinner
|
||||
AccountUtils.setupAccountSpinner(fragmentActivity, accountSpinner, accounts);
|
||||
|
||||
return new AlertDialog.Builder(fragmentActivity).setNegativeButton(
|
||||
R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.menu_export, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentActivity context = getActivity();
|
||||
ExportType type = exportTypeOptionsList.get(
|
||||
exportTypeOptions.getSelectedItemPosition());
|
||||
TrackFileFormat format = null;
|
||||
return new AlertDialog.Builder(fragmentActivity)
|
||||
.setNegativeButton(R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.menu_export, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentActivity context = getActivity();
|
||||
ExportType type = exportTypeOptionsList.get(
|
||||
exportTypeOptions.getSelectedItemPosition());
|
||||
TrackFileFormat format = null;
|
||||
|
||||
PreferencesUtils.setString(context, R.string.export_type_key, type.name());
|
||||
if (type == ExportType.GOOGLE_MAPS) {
|
||||
PreferencesUtils.setBoolean(context, R.string.export_google_maps_public_key,
|
||||
exportGoogleMapsOptions.getCheckedRadioButtonId()
|
||||
== R.id.export_google_maps_public);
|
||||
} else if (type == ExportType.GOOGLE_FUSION_TABLES) {
|
||||
PreferencesUtils.setBoolean(context, R.string.export_google_fusion_tables_public_key,
|
||||
exportGoogleFusionTablesOptions.getCheckedRadioButtonId()
|
||||
== R.id.export_google_fusion_tables_public);
|
||||
} else if (type == ExportType.EXTERNAL_STORAGE) {
|
||||
format = getTrackFileFormat(exportExternalStorageOptions.getCheckedRadioButtonId());
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.export_external_storage_format_key, format.name());
|
||||
}
|
||||
Account account;
|
||||
if (accounts.length == 0) {
|
||||
account = null;
|
||||
} else if (accounts.length == 1) {
|
||||
account = accounts[0];
|
||||
} else {
|
||||
account = accounts[accountSpinner.getSelectedItemPosition()];
|
||||
}
|
||||
AccountUtils.updateShareTrackAccountPreference(context, account);
|
||||
caller.onExportDone(type, format, account);
|
||||
}
|
||||
}).setTitle(R.string.export_title).setView(view).create();
|
||||
}
|
||||
|
||||
private void setupExportTypeOptions(FragmentActivity fragmentActivity) {
|
||||
boolean hideDrive = getArguments().getBoolean(KEY_HIDE_DRIVE);
|
||||
ExportType exportType = ExportType.valueOf(PreferencesUtils.getString(
|
||||
fragmentActivity, R.string.export_type_key, PreferencesUtils.EXPORT_TYPE_DEFAULT));
|
||||
|
||||
if (hideDrive && exportType == ExportType.GOOGLE_DRIVE) {
|
||||
exportType = ExportType.GOOGLE_MAPS;
|
||||
}
|
||||
|
||||
exportTypeOptionsList = new ArrayList<ExportDialogFragment.ExportType>();
|
||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
|
||||
getActivity(), android.R.layout.simple_spinner_item);
|
||||
if (accounts.length > 0) {
|
||||
if (!hideDrive) {
|
||||
exportTypeOptionsList.add(ExportType.GOOGLE_DRIVE);
|
||||
}
|
||||
exportTypeOptionsList.add(ExportType.GOOGLE_MAPS);
|
||||
exportTypeOptionsList.add(ExportType.GOOGLE_FUSION_TABLES);
|
||||
exportTypeOptionsList.add(ExportType.GOOGLE_SPREADSHEET);
|
||||
}
|
||||
exportTypeOptionsList.add(ExportType.EXTERNAL_STORAGE);
|
||||
|
||||
int selection = 0;
|
||||
for (int i = 0; i < exportTypeOptionsList.size(); i++) {
|
||||
ExportType type = exportTypeOptionsList.get(i);
|
||||
adapter.add(getString(type.resId));
|
||||
if (type == exportType) {
|
||||
selection = i;
|
||||
}
|
||||
}
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
exportTypeOptions.setAdapter(adapter);
|
||||
exportTypeOptions.setSelection(selection);
|
||||
exportTypeOptions.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
ExportType type = exportTypeOptionsList.get(position);
|
||||
exportGoogleMapsOptions.setVisibility(
|
||||
type == ExportType.GOOGLE_MAPS ? View.VISIBLE : View.GONE);
|
||||
exportGoogleFusionTablesOptions.setVisibility(
|
||||
type == ExportType.GOOGLE_FUSION_TABLES ? View.VISIBLE : View.GONE);
|
||||
exportExternalStorageOptions.setVisibility(
|
||||
type == ExportType.EXTERNAL_STORAGE ? View.VISIBLE : View.GONE);
|
||||
accountSpinner.setVisibility(
|
||||
accounts.length > 1 && type != ExportType.EXTERNAL_STORAGE ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
// Safely ignore
|
||||
}
|
||||
});
|
||||
PreferencesUtils.setString(context, R.string.export_type_key, type.name());
|
||||
if (type == ExportType.EXTERNAL_STORAGE) {
|
||||
format = getTrackFileFormat(exportExternalStorageOptions.getCheckedRadioButtonId());
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.export_external_storage_format_key, format.name());
|
||||
}
|
||||
caller.onExportDone(type, format);
|
||||
}
|
||||
})
|
||||
.setTitle(R.string.export_title).setView(view).create();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-58
@@ -1,58 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* A DialogFragment to install Google Earth.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class InstallEarthDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
public static final String INSTALL_EARTH_DIALOG_TAG = "installEarthDialog";
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
return new AlertDialog.Builder(getActivity()).setMessage(
|
||||
R.string.track_detail_install_earth_message).setNegativeButton(R.string.generic_no, null)
|
||||
.setPositiveButton(R.string.generic_yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent().setData(
|
||||
Uri.parse(GoogleEarthUtils.GOOGLE_EARTH_MARKET_URL));
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(
|
||||
getActivity(), R.string.track_detail_install_earth_error, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}).setTitle(R.string.track_detail_install_earth_title).create();
|
||||
}
|
||||
}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
|
||||
/**
|
||||
* A DialogFragment to select a map layer.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class MapLayerDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
public static final String MAP_LAYER_DIALOG_TAG = "mapLayer";
|
||||
|
||||
private static final int[] LAYERS = { R.string.menu_map, R.string.menu_satellite,
|
||||
R.string.menu_satellite_with_streets, R.string.menu_terrain };
|
||||
private static final int[] MAP_TYPES = { GoogleMap.MAP_TYPE_NORMAL, GoogleMap.MAP_TYPE_SATELLITE,
|
||||
GoogleMap.MAP_TYPE_HYBRID, GoogleMap.MAP_TYPE_TERRAIN };
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
String[] choices = new String[LAYERS.length];
|
||||
for (int i = 0; i < LAYERS.length; i++) {
|
||||
choices[i] = getString(LAYERS[i]);
|
||||
}
|
||||
|
||||
int mapType = PreferencesUtils.getInt(
|
||||
getActivity(), R.string.map_type_key, PreferencesUtils.MAP_TYPE_DEFAUlT);
|
||||
|
||||
return new AlertDialog.Builder(getActivity()).setNegativeButton(R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
|
||||
PreferencesUtils.setInt(getActivity(), R.string.map_type_key, MAP_TYPES[position]);
|
||||
}
|
||||
}).setSingleChoiceItems(choices, getPositionFromMapType(mapType), null)
|
||||
.setTitle(R.string.menu_map_layer).create();
|
||||
}
|
||||
|
||||
private int getPositionFromMapType(int mapType) {
|
||||
for (int i = 0; i < MAP_TYPES.length; i++) {
|
||||
if (MAP_TYPES[i] == mapType) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-136
@@ -1,136 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.TrackUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A DialogFragment to play multiple tracks.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class PlayMultipleDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
public static final String PLAY_MULTIPLE_DIALOG_TAG = "playMultipleDialog";
|
||||
|
||||
/**
|
||||
* Interface for caller of this dialog fragment.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface PlayMultipleCaller {
|
||||
|
||||
/**
|
||||
* Called when play multiple is done.
|
||||
*/
|
||||
public void onPlayMultipleDone(long[] trackIds);
|
||||
}
|
||||
|
||||
private static final String KEY_TRACK_ID = "trackId";
|
||||
|
||||
public static PlayMultipleDialogFragment newInstance(long trackId) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(KEY_TRACK_ID, trackId);
|
||||
|
||||
PlayMultipleDialogFragment fragment = new PlayMultipleDialogFragment();
|
||||
fragment.setArguments(bundle);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private PlayMultipleCaller caller;
|
||||
private String[] items;
|
||||
private boolean[] checkedItems;
|
||||
private long[] trackIds;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
caller = (PlayMultipleCaller) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(
|
||||
activity.toString() + " must implement " + PlayMultipleCaller.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
loadData();
|
||||
return new AlertDialog.Builder(getActivity()).setMultiChoiceItems(items, checkedItems, null)
|
||||
.setNegativeButton(R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.menu_play, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
SparseBooleanArray array = ((AlertDialog) dialog).getListView()
|
||||
.getCheckedItemPositions();
|
||||
caller.onPlayMultipleDone(getChecked(array));
|
||||
}
|
||||
}).setTitle(R.string.menu_play_multiple).create();
|
||||
}
|
||||
|
||||
private long[] getChecked(SparseBooleanArray array) {
|
||||
ArrayList<Long> checked = new ArrayList<Long>();
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
int key = array.keyAt(i);
|
||||
if (array.get(key)) {
|
||||
checked.add(trackIds[key]);
|
||||
}
|
||||
}
|
||||
long[] result = new long[checked.size()];
|
||||
for (int i = 0; i < checked.size(); i++) {
|
||||
result[i] = checked.get(i).longValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
long trackId = getArguments().getLong(KEY_TRACK_ID);
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity());
|
||||
Cursor cursor = myTracksProviderUtils.getTrackCursor(null, null, TrackUtils.TRACK_SORT_ORDER);
|
||||
|
||||
if (cursor == null) {
|
||||
items = new String[] {};
|
||||
checkedItems = new boolean[] {};
|
||||
trackIds = new long[] {};
|
||||
} else {
|
||||
int count = cursor.getCount();
|
||||
items = new String[count];
|
||||
checkedItems = new boolean[count];
|
||||
trackIds = new long[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
cursor.moveToPosition(i);
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
items[i] = track.getName();
|
||||
checkedItems[i] = trackId != -1L && track.getId() == trackId;
|
||||
trackIds[i] = track.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-210
@@ -1,210 +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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.util.AccountUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.widget.SimpleCursorAdapter;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.FilterQueryProvider;
|
||||
import android.widget.MultiAutoCompleteTextView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* A DialogFragment to share a track.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class ShareTrackDialogFragment extends AbstractMyTracksDialogFragment {
|
||||
|
||||
/**
|
||||
* Interface for caller of this dialog fragment.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface ShareTrackCaller {
|
||||
|
||||
/**
|
||||
* Called when share track is done.
|
||||
*
|
||||
* @param trackId the track id
|
||||
* @param makePublic true to make the track public
|
||||
* @param emails the emails to share the track with
|
||||
* @param account the google drive account
|
||||
*/
|
||||
public void onShareTrackDone(long trackId, boolean makePublic, String emails, Account account);
|
||||
}
|
||||
|
||||
public static final String SHARE_TRACK_DIALOG_TAG = "shareTrackDialog";
|
||||
|
||||
private static final String KEY_TRACK_ID = "trackId";
|
||||
|
||||
public static ShareTrackDialogFragment newInstance(long trackId) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(KEY_TRACK_ID, trackId);
|
||||
|
||||
ShareTrackDialogFragment shareleTrackDialogFragment = new ShareTrackDialogFragment();
|
||||
shareleTrackDialogFragment.setArguments(bundle);
|
||||
return shareleTrackDialogFragment;
|
||||
}
|
||||
|
||||
private ShareTrackCaller caller;
|
||||
private Account[] accounts;
|
||||
|
||||
// UI elements
|
||||
private CheckBox publicCheckBox;
|
||||
private CheckBox inviteCheckBox;
|
||||
private MultiAutoCompleteTextView multiAutoCompleteTextView;
|
||||
private Spinner accountSpinner;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
caller = (ShareTrackCaller) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(
|
||||
activity.toString() + " must implement " + ShareTrackCaller.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog() {
|
||||
FragmentActivity fragmentActivity = getActivity();
|
||||
accounts = AccountManager.get(fragmentActivity).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
|
||||
if (accounts.length == 0) {
|
||||
return new AlertDialog.Builder(fragmentActivity).setMessage(
|
||||
R.string.send_google_no_account_message).setTitle(R.string.send_google_no_account_title)
|
||||
.setPositiveButton(R.string.generic_ok, null).create();
|
||||
}
|
||||
|
||||
// Get all the views
|
||||
View view = fragmentActivity.getLayoutInflater().inflate(R.layout.share_track, null);
|
||||
publicCheckBox = (CheckBox) view.findViewById(R.id.share_track_public);
|
||||
inviteCheckBox = (CheckBox) view.findViewById(R.id.share_track_invite);
|
||||
multiAutoCompleteTextView = (MultiAutoCompleteTextView) view.findViewById(
|
||||
R.id.share_track_emails);
|
||||
accountSpinner = (Spinner) view.findViewById(R.id.share_track_account);
|
||||
|
||||
// Setup publicCheckBox
|
||||
publicCheckBox.setChecked(PreferencesUtils.getBoolean(
|
||||
fragmentActivity, R.string.share_track_public_key,
|
||||
PreferencesUtils.SHARE_TRACK_PUBLIC_DEFAULT));
|
||||
|
||||
// Setup inviteCheckBox
|
||||
inviteCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
multiAutoCompleteTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
inviteCheckBox.setChecked(PreferencesUtils.getBoolean(
|
||||
fragmentActivity, R.string.share_track_invite_key,
|
||||
PreferencesUtils.SHARE_TRACK_INVITE_DEFAULT));
|
||||
|
||||
// Setup multiAutoCompleteTextView
|
||||
multiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
|
||||
SimpleCursorAdapter adapter = new SimpleCursorAdapter(fragmentActivity,
|
||||
R.layout.add_emails_item, getAutoCompleteCursor(fragmentActivity, null), new String[] {
|
||||
ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Email.DATA },
|
||||
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
|
||||
adapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
|
||||
@Override
|
||||
public CharSequence convertToString(Cursor cursor) {
|
||||
int index = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
|
||||
return cursor.getString(index).trim();
|
||||
}
|
||||
});
|
||||
adapter.setFilterQueryProvider(new FilterQueryProvider() {
|
||||
@Override
|
||||
public Cursor runQuery(CharSequence constraint) {
|
||||
return getAutoCompleteCursor(getActivity(), constraint);
|
||||
}
|
||||
});
|
||||
multiAutoCompleteTextView.setAdapter(adapter);
|
||||
|
||||
// Setup accountSpinner
|
||||
accountSpinner.setVisibility(accounts.length > 1 ? View.VISIBLE : View.GONE);
|
||||
AccountUtils.setupAccountSpinner(fragmentActivity, accountSpinner, accounts);
|
||||
|
||||
return new AlertDialog.Builder(fragmentActivity).setNegativeButton(
|
||||
R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
FragmentActivity context = getActivity();
|
||||
if (!publicCheckBox.isChecked() && !inviteCheckBox.isChecked()) {
|
||||
Toast.makeText(context, R.string.share_track_no_selection, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
String acl = multiAutoCompleteTextView.getText().toString().trim();
|
||||
if (!publicCheckBox.isChecked() && acl.equals("")) {
|
||||
Toast.makeText(context, R.string.share_track_no_emails, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
PreferencesUtils.setBoolean(
|
||||
context, R.string.share_track_public_key, publicCheckBox.isChecked());
|
||||
PreferencesUtils.setBoolean(
|
||||
context, R.string.share_track_invite_key, inviteCheckBox.isChecked());
|
||||
Account account = accounts.length > 1 ? accounts[accountSpinner
|
||||
.getSelectedItemPosition()]
|
||||
: accounts[0];
|
||||
AccountUtils.updateShareTrackAccountPreference(context, account);
|
||||
caller.onShareTrackDone(
|
||||
getArguments().getLong(KEY_TRACK_ID), publicCheckBox.isChecked(), acl, account);
|
||||
}
|
||||
}).setTitle(R.string.share_track_title).setView(view).create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the auto complete cursor.
|
||||
*
|
||||
* @param constraint the constraint
|
||||
*/
|
||||
private Cursor getAutoCompleteCursor(FragmentActivity fragmentActivity, CharSequence constraint) {
|
||||
String order = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
|
||||
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";
|
||||
if (constraint != null) {
|
||||
selection += " AND (" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%" + constraint
|
||||
+ "%' OR " + ContactsContract.CommonDataKinds.Email.DATA + " LIKE '%" + constraint
|
||||
+ "%' )";
|
||||
}
|
||||
String[] projection = new String[] { ContactsContract.Contacts._ID,
|
||||
ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Email.DATA };
|
||||
Uri uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
|
||||
return fragmentActivity.getContentResolver().query(uri, projection, selection, null, order);
|
||||
}
|
||||
}
|
||||
+8
-14
@@ -15,6 +15,12 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.content.DescriptionGenerator;
|
||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
@@ -26,15 +32,8 @@ 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.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
@@ -188,7 +187,7 @@ public class KmlTrackWriter implements TrackWriter {
|
||||
@Override
|
||||
public void writeBeginTracks() {
|
||||
if (printWriter != null && multiple) {
|
||||
printWriter.println("<Folder id=\"" + GoogleEarthUtils.TOUR_FEATURE_ID_VALUE + "\">");
|
||||
printWriter.println("<Folder id=tour>");
|
||||
printWriter.println("<name>" + context.getString(R.string.generic_tracks) + "</name>");
|
||||
printWriter.println("<open>1</open>");
|
||||
}
|
||||
@@ -206,12 +205,7 @@ public class KmlTrackWriter implements TrackWriter {
|
||||
if (printWriter != null) {
|
||||
String name = context.getString(R.string.marker_label_start, track.getName());
|
||||
writePlacemark(name, "", "", START_STYLE, startLocation);
|
||||
if (multiple) {
|
||||
// No need to add TOUR_FEATURE_ID_VALUE
|
||||
printWriter.println("<Placemark>");
|
||||
} else {
|
||||
printWriter.println("<Placemark id=\"" + GoogleEarthUtils.TOUR_FEATURE_ID_VALUE + "\">");
|
||||
}
|
||||
printWriter.println("<Placemark>");
|
||||
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
|
||||
printWriter.println(
|
||||
"<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
|
||||
|
||||
+1
-7
@@ -19,7 +19,6 @@ package com.google.android.apps.mytracks.io.file.exporter;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
@@ -200,12 +199,7 @@ public class SaveActivity extends Activity {
|
||||
totalCount = aTotalCount;
|
||||
savedPath = aSavedPath;
|
||||
removeDialog(DIALOG_PROGRESS_ID);
|
||||
if (playTrack && successCount == 1 && totalCount == 1 && savedPath != null) {
|
||||
startActivity(GoogleEarthUtils.getPlayInEarthIntent(this, savedPath));
|
||||
finish();
|
||||
} else {
|
||||
showDialog(DIALOG_RESULT_ID);
|
||||
}
|
||||
showDialog(DIALOG_RESULT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -16,12 +16,12 @@
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
+1
-1
@@ -21,11 +21,11 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -1,604 +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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
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.KmzTrackImporter;
|
||||
import com.google.android.apps.mytracks.io.file.importer.TrackImporter;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
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.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import com.google.api.services.drive.Drive.Changes;
|
||||
import com.google.api.services.drive.Drive.Files;
|
||||
import com.google.api.services.drive.model.About;
|
||||
import com.google.api.services.drive.model.Change;
|
||||
import com.google.api.services.drive.model.ChangeList;
|
||||
import com.google.api.services.drive.model.File;
|
||||
import com.google.api.services.drive.model.FileList;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.AbstractThreadedSyncAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.Context;
|
||||
import android.content.SyncResult;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* SyncAdapter to sync tracks with Google Drive.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
||||
private static final String TAG = SyncAdapter.class.getSimpleName();
|
||||
|
||||
// drive.about.get fields. Contains one field, largestChangeId
|
||||
private static final String ABOUT_GET_FIELDS = "largestChangeId";
|
||||
|
||||
private final Context context;
|
||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||
private Drive drive;
|
||||
private String driveAccountName; // the account name associated with the drive
|
||||
private String folderId;
|
||||
|
||||
public SyncAdapter(Context context) {
|
||||
super(context, true);
|
||||
this.context = context;
|
||||
this.myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority,
|
||||
ContentProviderClient provider, SyncResult syncResult) {
|
||||
if (!PreferencesUtils.getBoolean(
|
||||
context, R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (account == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the folder id..
|
||||
*/
|
||||
private String getFolderId() throws IOException {
|
||||
File folder = SyncUtils.getMyTracksFolder(context, drive);
|
||||
if (folder == null) {
|
||||
throw new IOException("folder is null");
|
||||
}
|
||||
String id = folder.getId();
|
||||
if (id == null) {
|
||||
throw new IOException("folder id is null");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs initial sync.
|
||||
*/
|
||||
private void performInitialSync() throws IOException {
|
||||
|
||||
// Get the largest change id first to avoid race conditions
|
||||
About about = drive.about().get().setFields(ABOUT_GET_FIELDS).execute();
|
||||
long largestChangeId = about.getLargestChangeId();
|
||||
|
||||
// Get all the KML/KMZ files in the "My Drive:/My Tracks" folder
|
||||
Files.List myTracksFolderRequest = drive.files()
|
||||
.list().setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId));
|
||||
Map<String, File> myTracksFolderMap = getFiles(myTracksFolderRequest, true);
|
||||
|
||||
// Handle tracks that are already uploaded to Google Drive
|
||||
Set<String> syncedDriveIds = updateSyncedTracks();
|
||||
for (String driveId : syncedDriveIds) {
|
||||
myTracksFolderMap.remove(driveId);
|
||||
}
|
||||
|
||||
// Get all the KML/KMZ files in the "Shared with me:/" folder
|
||||
Files.List sharedWithMeRequest = drive.files()
|
||||
.list().setQ(SyncUtils.SHARED_WITH_ME_FILES_QUERY);
|
||||
Map<String, File> sharedWithMeMap = getFiles(sharedWithMeRequest, false);
|
||||
|
||||
try {
|
||||
insertNewTracks(myTracksFolderMap.values());
|
||||
insertNewTracks(sharedWithMeMap.values());
|
||||
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, largestChangeId);
|
||||
} catch (IOException e) {
|
||||
|
||||
// Remove all imported tracks
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
if (!syncedDriveIds.contains(track.getDriveId())) {
|
||||
myTracksProviderUtils.deleteTrack(context, track.getId());
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates synced tracks.
|
||||
*
|
||||
* @return drive ids of the synced tracks
|
||||
*/
|
||||
private Set<String> updateSyncedTracks() throws IOException {
|
||||
Set<String> result = new HashSet<String>();
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
String driveId = track.getDriveId();
|
||||
if (driveId != null && !driveId.equals("")) {
|
||||
if (!track.isSharedWithMe()) {
|
||||
File driveFile = drive.files().get(driveId).execute();
|
||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)) {
|
||||
merge(track, driveFile);
|
||||
result.add(driveId);
|
||||
} else {
|
||||
/*
|
||||
* Track has a drive id, but the drive id is no longer valid.
|
||||
* E.g., the file is moved to another folder. Clear the drive
|
||||
* id.
|
||||
*/
|
||||
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs incremental sync.
|
||||
*
|
||||
* @param largestChangeId the largest change id
|
||||
*/
|
||||
private void performIncrementalSync(long largestChangeId) throws IOException {
|
||||
|
||||
// Handle deleted tracks
|
||||
String driveDeletedList = PreferencesUtils.getString(
|
||||
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
||||
if (!PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT.equals(driveDeletedList)) {
|
||||
String deletedIds[] = TextUtils.split(driveDeletedList, ";");
|
||||
for (String driveId : deletedIds) {
|
||||
deleteDriveFile(driveId, true);
|
||||
}
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
||||
}
|
||||
|
||||
// Handle edited tracks
|
||||
String driveEditedList = PreferencesUtils.getString(
|
||||
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
||||
if (!PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT.equals(driveEditedList)) {
|
||||
String editedIds[] = TextUtils.split(driveEditedList, ";");
|
||||
for (String id : editedIds) {
|
||||
Track track = myTracksProviderUtils.getTrack(Long.valueOf(id));
|
||||
if (track == null) {
|
||||
continue;
|
||||
}
|
||||
if (track.isSharedWithMe()) {
|
||||
continue;
|
||||
}
|
||||
String driveId = track.getDriveId();
|
||||
if (driveId == null || driveId.equals("")) {
|
||||
continue;
|
||||
}
|
||||
File driveFile = drive.files().get(driveId).execute();
|
||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)) {
|
||||
merge(track, driveFile);
|
||||
}
|
||||
}
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
||||
}
|
||||
|
||||
// Handle changes from Google Drive
|
||||
Map<String, File> changes = new HashMap<String, File>();
|
||||
long newLargestChangeId = getDriveChangesInfo(largestChangeId, changes);
|
||||
if (newLargestChangeId != largestChangeId) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
// Get all the local tracks with drive file id
|
||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
String driveId = track.getDriveId();
|
||||
|
||||
if (changes.containsKey(driveId)) {
|
||||
|
||||
// Track has changed
|
||||
File driveFile = changes.get(driveId);
|
||||
if (driveFile == null) {
|
||||
Log.d(TAG, "Delete local track " + track.getName());
|
||||
myTracksProviderUtils.deleteTrack(context, track.getId());
|
||||
} else {
|
||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)
|
||||
|| SyncUtils.isInSharedWithMe(driveFile)) {
|
||||
merge(track, driveFile);
|
||||
} else {
|
||||
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
||||
}
|
||||
}
|
||||
changes.remove(driveId);
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
// Insert valid new drive file changes as new tracks
|
||||
Iterator<String> iterator = changes.keySet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
String driveId = iterator.next();
|
||||
File file = changes.get(driveId);
|
||||
if (!SyncUtils.isInMyTracksAndValid(file, folderId)
|
||||
&& !SyncUtils.isInSharedWithMeAndValid(file)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
insertNewTracks(changes.values());
|
||||
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, newLargestChangeId);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts new drive files from tracks without a drive id.
|
||||
*/
|
||||
private void insertNewDriveFiles() throws IOException {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.NO_DRIVE_ID_TRACKS_QUERY, null, null);
|
||||
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
if (track.getId() == recordingTrackId) {
|
||||
continue;
|
||||
}
|
||||
// If not successful, the next sync will retry again
|
||||
SyncUtils.insertDriveFile(
|
||||
drive, folderId, context, myTracksProviderUtils, track, true, true);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts new tracks from a collection of drive files.
|
||||
*
|
||||
* @param driveFiles the drive files
|
||||
*/
|
||||
private void insertNewTracks(Collection<File> driveFiles) throws IOException {
|
||||
for (File driveFile : driveFiles) {
|
||||
if (driveFile == null) {
|
||||
return;
|
||||
}
|
||||
updateTrack(-1L, driveFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the files from a request.
|
||||
*
|
||||
* @param request the request
|
||||
* @param excludeSharedWithMe true to exclude shared with me files
|
||||
* @return a map of file id to file
|
||||
*/
|
||||
private Map<String, File> getFiles(Files.List request, boolean excludeSharedWithMe)
|
||||
throws IOException {
|
||||
Map<String, File> idToFileMap = new HashMap<String, File>();
|
||||
do {
|
||||
FileList files = request.execute();
|
||||
|
||||
for (File file : files.getItems()) {
|
||||
if (excludeSharedWithMe && file.getSharedWithMeDate() != null) {
|
||||
continue;
|
||||
}
|
||||
idToFileMap.put(file.getId(), file);
|
||||
}
|
||||
request.setPageToken(files.getNextPageToken());
|
||||
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
|
||||
return idToFileMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the drive changes info in the My Tracks folder, including deleted
|
||||
* files.
|
||||
*
|
||||
* @param changeId the largest change id
|
||||
* @param changes a map of drive id to file for the changes
|
||||
* @return an updated largest change id
|
||||
*/
|
||||
private long getDriveChangesInfo(long changeId, Map<String, File> changes) throws IOException {
|
||||
Changes.List request = drive.changes().list().setStartChangeId(changeId + 1);
|
||||
do {
|
||||
ChangeList changeList = request.execute();
|
||||
long newId = changeList.getLargestChangeId().longValue();
|
||||
|
||||
for (Change change : changeList.getItems()) {
|
||||
if (change.getDeleted()) {
|
||||
changes.put(change.getFileId(), null);
|
||||
} else {
|
||||
File file = change.getFile();
|
||||
if (file.getLabels().getTrashed()) {
|
||||
changes.put(change.getFileId(), null);
|
||||
} else {
|
||||
changes.put(change.getFileId(), file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newId > changeId) {
|
||||
changeId = newId;
|
||||
}
|
||||
request.setPageToken(changeList.getNextPageToken());
|
||||
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
|
||||
Log.d(TAG, "Got drive changes: " + changes.size() + " " + changeId);
|
||||
return changeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a track with a drive file.
|
||||
*
|
||||
* @param track the track
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
private void merge(Track track, File driveFile) throws IOException {
|
||||
long modifiedTime = track.getModifiedTime();
|
||||
long driveModifiedTime = driveFile.getModifiedDate().getValue();
|
||||
if (modifiedTime > driveModifiedTime) {
|
||||
Log.d(TAG, "Updating track change for track " + track.getName() + " and drive file "
|
||||
+ driveFile.getTitle());
|
||||
if (!SyncUtils.updateDriveFile(
|
||||
drive, driveFile, context, myTracksProviderUtils, track, true)) {
|
||||
Log.e(TAG, "Unable to update drive file");
|
||||
track.setModifiedTime(driveModifiedTime);
|
||||
myTracksProviderUtils.updateTrack(track);
|
||||
}
|
||||
} else if (modifiedTime < driveModifiedTime) {
|
||||
Log.d(TAG, "Updating drive change for track " + track.getName() + " and drive file "
|
||||
+ driveFile.getTitle());
|
||||
if (!updateTrack(track.getId(), driveFile)) {
|
||||
Log.e(TAG, "Unable to update drive change");
|
||||
// The track could have been deleted in the unsuccessful update
|
||||
track = myTracksProviderUtils.getTrack(track.getId());
|
||||
if (track != null) {
|
||||
track.setModifiedTime(driveModifiedTime);
|
||||
myTracksProviderUtils.updateTrack(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a track based on a drive file. Returns true if successful.
|
||||
*
|
||||
* @param trackId the track id. -1L to insert a new track
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
private boolean updateTrack(final long trackId, File driveFile) throws IOException {
|
||||
Track track = null;
|
||||
boolean success = false;
|
||||
try {
|
||||
track = importDriveFile(trackId, driveFile);
|
||||
if (track == null) {
|
||||
return false;
|
||||
}
|
||||
File updatedDriveFile;
|
||||
String trackName = FileUtils.getName(driveFile.getTitle());
|
||||
if (SyncUtils.isInMyTracks(driveFile, folderId) && !track.getName().equals(trackName)) {
|
||||
track.setName(trackName);
|
||||
|
||||
/*
|
||||
* The drive file title and the track name inside the drive file do not
|
||||
* match, update the drive file.
|
||||
*/
|
||||
java.io.File file = null;
|
||||
try {
|
||||
file = SyncUtils.getTempFile(context, myTracksProviderUtils, track, true);
|
||||
updatedDriveFile = SyncUtils.updateDriveFile(
|
||||
drive, driveFile, trackName + "." + KmzTrackExporter.KMZ_EXTENSION, file, true);
|
||||
|
||||
if (updatedDriveFile == null) {
|
||||
Log.e(TAG, "Unable to update drive file");
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
if (file != null) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updatedDriveFile = driveFile;
|
||||
}
|
||||
|
||||
SyncUtils.updateTrack(myTracksProviderUtils, track, updatedDriveFile);
|
||||
success = true;
|
||||
return true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
// if the track is new, delete it
|
||||
if (trackId == -1L && track != null) {
|
||||
myTracksProviderUtils.deleteTrack(context, track.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports drive file to track.
|
||||
*
|
||||
* @param trackId the track id. -1L to insert a new track
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
private Track importDriveFile(long trackId, File driveFile) throws IOException {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = downloadDriveFile(driveFile, true);
|
||||
if (inputStream == null) {
|
||||
Log.e(TAG, "Unable to import drive file. Input stream is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
TrackImporter trackImporter;
|
||||
boolean useKmz = KmzTrackExporter.KMZ_EXTENSION.equals(driveFile.getFileExtension());
|
||||
if (useKmz) {
|
||||
if (trackId == -1L) {
|
||||
Uri uri = myTracksProviderUtils.insertTrack(new Track());
|
||||
trackId = Long.parseLong(uri.getLastPathSegment());
|
||||
}
|
||||
trackImporter = new KmzTrackImporter(context, trackId);
|
||||
} else {
|
||||
trackImporter = new KmlFileTrackImporter(context, trackId);
|
||||
}
|
||||
|
||||
long importedId = trackImporter.importFile(inputStream);
|
||||
if (importedId == -1L) {
|
||||
Log.e(TAG, "Unable to import drive file. Imported id is -1L.");
|
||||
return null;
|
||||
}
|
||||
Track track = myTracksProviderUtils.getTrack(importedId);
|
||||
if (track == null) {
|
||||
Log.e(TAG, "Unable to import drive file. Imported track is null.");
|
||||
return null;
|
||||
} else {
|
||||
return track;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to import drive file.", e);
|
||||
return null;
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a drive file.
|
||||
*
|
||||
* @param driveId the drive id
|
||||
* @param canRetry true if can retry the request
|
||||
* @throws IOException
|
||||
*/
|
||||
private void deleteDriveFile(String driveId, boolean canRetry) throws IOException {
|
||||
try {
|
||||
File driveFile = drive.files().get(driveId).execute();
|
||||
if (SyncUtils.isInMyTracks(driveFile, folderId)) {
|
||||
if (!driveFile.getLabels().getTrashed()) {
|
||||
drive.files().trash(driveId).execute();
|
||||
}
|
||||
// if trashed, ignore
|
||||
} else if (SyncUtils.isInSharedWithMe(driveFile)) {
|
||||
if (!driveFile.getLabels().getTrashed()) {
|
||||
drive.files().delete(driveId).execute();
|
||||
}
|
||||
// if trashed, ignore
|
||||
}
|
||||
} catch (UserRecoverableAuthIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
if (canRetry) {
|
||||
deleteDriveFile(driveId, false);
|
||||
return;
|
||||
}
|
||||
Log.e(TAG, "Unable to delete Drive file for " + driveId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a drive file.
|
||||
*
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
private InputStream downloadDriveFile(File driveFile, boolean canRetry) throws IOException {
|
||||
if (driveFile.getDownloadUrl() == null || driveFile.getDownloadUrl().length() == 0) {
|
||||
Log.d(TAG, "Drive file download url doesn't exist: " + driveFile.getTitle());
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
HttpResponse httpResponse = drive.getRequestFactory()
|
||||
.buildGetRequest(new GenericUrl(driveFile.getDownloadUrl())).execute();
|
||||
if (httpResponse == null) {
|
||||
Log.e(TAG, "http response is null");
|
||||
return null;
|
||||
}
|
||||
return httpResponse.getContent();
|
||||
} catch (UserRecoverableAuthIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
if (canRetry) {
|
||||
return downloadDriveFile(driveFile, false);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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.sync;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Service to sync with Google Drive.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SyncService extends Service {
|
||||
|
||||
private static final Object lock = new Object();
|
||||
|
||||
private static SyncAdapter syncAdapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
synchronized (lock) {
|
||||
if (syncAdapter == null) {
|
||||
syncAdapter = new SyncAdapter(getApplicationContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return syncAdapter.getSyncAdapterBinder();
|
||||
}
|
||||
}
|
||||
@@ -1,557 +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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.io.file.exporter.FileTrackExporter;
|
||||
import com.google.android.apps.mytracks.io.file.exporter.KmzTrackExporter;
|
||||
import com.google.android.apps.mytracks.io.file.exporter.TrackExporter;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.client.extensions.android.http.AndroidHttp;
|
||||
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.FileContent;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import com.google.api.services.drive.Drive.Files.List;
|
||||
import com.google.api.services.drive.model.File;
|
||||
import com.google.api.services.drive.model.FileList;
|
||||
import com.google.api.services.drive.model.ParentReference;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Utilities for Google Drive sync.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SyncUtils {
|
||||
|
||||
// Get tracks with drive id
|
||||
public static final String DRIVE_ID_TRACKS_QUERY = TracksColumns.DRIVEID + " IS NOT NULL AND "
|
||||
+ TracksColumns.DRIVEID + "!=''";
|
||||
|
||||
// Get tracks without drive id
|
||||
public static final String NO_DRIVE_ID_TRACKS_QUERY = TracksColumns.DRIVEID + " IS NULL OR "
|
||||
+ TracksColumns.DRIVEID + "=''";
|
||||
|
||||
// KML mime type
|
||||
public static final String KML_MIME_TYPE = "application/vnd.google-earth.kml+xml";
|
||||
|
||||
// KMZ mime type
|
||||
public static final String KMZ_MIME_TYPE = "application/vnd.google-earth.kmz";
|
||||
|
||||
// KML and KMZ mime types
|
||||
private static final String KML_KMZ_MINE_TYPES = "not (mimeType != '" + KML_MIME_TYPE
|
||||
+ "' and mimeType != '" + KMZ_MIME_TYPE + "')";
|
||||
|
||||
// Get KML/KMZ files in the My Tracks folder
|
||||
public static final String MY_TRACKS_FOLDER_FILES_QUERY = "'%s' in parents and "
|
||||
+ KML_KMZ_MINE_TYPES + " and trashed = false";
|
||||
|
||||
// Get shared with me KML/KMZ files
|
||||
public static final String SHARED_WITH_ME_FILES_QUERY = "sharedWithMe and " + KML_KMZ_MINE_TYPES
|
||||
+ " and trashed = false";
|
||||
|
||||
// Folder mime type
|
||||
private static final String FOLDER_MIME_TYPE = "application/vnd.google-apps.folder";
|
||||
|
||||
// Get My Tracks folder
|
||||
@VisibleForTesting
|
||||
public static final String MY_TRACKS_FOLDER_QUERY =
|
||||
"'root' in parents and title = '%s' and mimeType = '" + FOLDER_MIME_TYPE
|
||||
+ "' and trashed = false";
|
||||
|
||||
private static final String TAG = SyncUtils.class.getSimpleName();
|
||||
private static final String SYNC_AUTHORITY = "com.google.android.maps.mytracks";
|
||||
|
||||
private SyncUtils() {}
|
||||
|
||||
/**
|
||||
* Syncs now for the current account.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void syncNow(Context context) {
|
||||
Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
context, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
for (Account account : accounts) {
|
||||
if (account.name.equals(googleAccount)) {
|
||||
ContentResolver.cancelSync(account, SYNC_AUTHORITY);
|
||||
ContentResolver.requestSync(account, SYNC_AUTHORITY, new Bundle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables sync.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void disableSync(Context context) {
|
||||
// Set preference
|
||||
PreferencesUtils.setBoolean(
|
||||
context, R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
|
||||
// Disable sync for all accounts
|
||||
disableSyncForAll(context);
|
||||
|
||||
// Clear sync state
|
||||
clearSyncState(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables sync for all accounts.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
private static void disableSyncForAll(Context context) {
|
||||
Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
for (Account account : accounts) {
|
||||
ContentResolver.cancelSync(account, SYNC_AUTHORITY);
|
||||
ContentResolver.setIsSyncable(account, SYNC_AUTHORITY, 0);
|
||||
ContentResolver.setSyncAutomatically(account, SYNC_AUTHORITY, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if sync is active.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static boolean isSyncActive(Context context) {
|
||||
Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
for (Account account : accounts) {
|
||||
if (ContentResolver.isSyncActive(account, SYNC_AUTHORITY)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables sync.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void enableSync(Context context) {
|
||||
// Set preference
|
||||
PreferencesUtils.setBoolean(context, R.string.drive_sync_key, true);
|
||||
|
||||
// Disable sync for all accounts
|
||||
disableSyncForAll(context);
|
||||
|
||||
// Turn on sync
|
||||
ContentResolver.setMasterSyncAutomatically(true);
|
||||
|
||||
// Enable sync for account
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
context, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
enableSyncForAccount(new Account(googleAccount, Constants.ACCOUNT_TYPE));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables sync for an account.
|
||||
*
|
||||
* @param account the account
|
||||
*/
|
||||
private static void enableSyncForAccount(Account account) {
|
||||
ContentResolver.setIsSyncable(account, SYNC_AUTHORITY, 1);
|
||||
ContentResolver.setSyncAutomatically(account, SYNC_AUTHORITY, true);
|
||||
ContentResolver.requestSync(account, SYNC_AUTHORITY, new Bundle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the sync state. Assumes sync is turned off. Do not want clearing the
|
||||
* sync state to cause sync activities.
|
||||
*/
|
||||
private static void clearSyncState(Context context) {
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||
if (track.isSharedWithMe()) {
|
||||
myTracksProviderUtils.deleteTrack(context, track.getId());
|
||||
} else {
|
||||
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key,
|
||||
PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT);
|
||||
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
||||
|
||||
// Clear the drive_deleted_list_key last
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the drive service.
|
||||
*
|
||||
* @param credential the credential
|
||||
*/
|
||||
public static Drive getDriveService(GoogleAccountCredential credential) {
|
||||
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the My Tracks folder. Creates one if necessary.
|
||||
*
|
||||
* @param context the context
|
||||
* @param drive the drive
|
||||
*/
|
||||
public static File getMyTracksFolder(Context context, Drive drive) throws IOException {
|
||||
String folderName = context.getString(R.string.my_tracks_app_name);
|
||||
List list = drive.files()
|
||||
.list().setQ(String.format(Locale.US, MY_TRACKS_FOLDER_QUERY, folderName));
|
||||
FileList result = list.execute();
|
||||
for (File file : result.getItems()) {
|
||||
if (file.getSharedWithMeDate() == null) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
File file = new File();
|
||||
file.setTitle(folderName);
|
||||
file.setMimeType(FOLDER_MIME_TYPE);
|
||||
return drive.files().insert(file).execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a drive file is a KML or KMZ file in the My Tracks folder.
|
||||
*
|
||||
* @param driveFile the drive file
|
||||
* @param folderId the My Tracks folder id
|
||||
*/
|
||||
public static boolean isInMyTracks(File driveFile, String folderId) {
|
||||
if (driveFile == null) {
|
||||
return false;
|
||||
}
|
||||
String mimeType = driveFile.getMimeType();
|
||||
if (!SyncUtils.KML_MIME_TYPE.equals(mimeType) && !SyncUtils.KMZ_MIME_TYPE.equals(mimeType)) {
|
||||
return false;
|
||||
}
|
||||
if (driveFile.getSharedWithMeDate() != null) {
|
||||
return false;
|
||||
}
|
||||
for (ParentReference parentReference : driveFile.getParents()) {
|
||||
String id = parentReference.getId();
|
||||
if (id != null && id.equals(folderId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a drive file is a KML or KMZ file in the My Tracks folder
|
||||
* and not trashed.
|
||||
*
|
||||
* @param driveFile the drive file
|
||||
* @param folderId the My Tracks folder id
|
||||
*/
|
||||
public static boolean isInMyTracksAndValid(File driveFile, String folderId) {
|
||||
return isInMyTracks(driveFile, folderId) && !driveFile.getLabels().getTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a drive file is a KML or KMZ file in the Shared with me
|
||||
* directory.
|
||||
*
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
public static boolean isInSharedWithMe(File driveFile) {
|
||||
if (driveFile == null) {
|
||||
return false;
|
||||
}
|
||||
String mimeType = driveFile.getMimeType();
|
||||
if (!SyncUtils.KML_MIME_TYPE.equals(mimeType) && !SyncUtils.KMZ_MIME_TYPE.equals(mimeType)) {
|
||||
return false;
|
||||
}
|
||||
return driveFile.getSharedWithMeDate() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a drive file is a KML or KMZ file in the Shared with me
|
||||
* directory and is not trashed.
|
||||
*
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
public static boolean isInSharedWithMeAndValid(File driveFile) {
|
||||
return isInSharedWithMe(driveFile) && !driveFile.getLabels().getTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a drive file using info from a track.
|
||||
*
|
||||
* @param drive the drive
|
||||
* @param folderId the folder id
|
||||
* @param context the context
|
||||
* @param myTracksProviderUtils the myTracksProviderUtils
|
||||
* @param track the track
|
||||
* @param canRetry true if can retry
|
||||
* @param updateTrack true to update track
|
||||
* @return the added drive file or null.
|
||||
*/
|
||||
public static File insertDriveFile(Drive drive, String folderId, Context context,
|
||||
MyTracksProviderUtils myTracksProviderUtils, Track track, boolean canRetry, boolean updateTrack)
|
||||
throws IOException {
|
||||
java.io.File file = null;
|
||||
try {
|
||||
file = getTempFile(context, myTracksProviderUtils, track, true);
|
||||
|
||||
if (file == null) {
|
||||
Log.e(TAG, "Unable to add Drive file. File is null for track " + track.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Add Drive file for track " + track.getName());
|
||||
File uploadedFile = insertDriveFile(drive, folderId, track.getName(), file, canRetry);
|
||||
if (uploadedFile == null) {
|
||||
Log.e(TAG, "Unable to add Drive file. Uploaded file is null for track " + track.getName());
|
||||
return null;
|
||||
}
|
||||
if (updateTrack) {
|
||||
SyncUtils.updateTrack(myTracksProviderUtils, track, uploadedFile);
|
||||
}
|
||||
return uploadedFile;
|
||||
} finally {
|
||||
if (file != null) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a drive file using info from a track file.
|
||||
*
|
||||
* @param drive the drive
|
||||
* @param folderId the folder id
|
||||
* @param trackName the track name
|
||||
* @param file the track file
|
||||
* @param canRetry true if can retry
|
||||
*/
|
||||
private static File insertDriveFile(
|
||||
Drive drive, String folderId, String trackName, java.io.File file, boolean canRetry)
|
||||
throws IOException {
|
||||
try {
|
||||
// file's parent
|
||||
ParentReference parentReference = new ParentReference();
|
||||
parentReference.setId(folderId);
|
||||
ArrayList<ParentReference> parents = new ArrayList<ParentReference>();
|
||||
parents.add(parentReference);
|
||||
|
||||
// file's metadata
|
||||
File newMetaData = new File();
|
||||
newMetaData.setTitle(trackName + "." + KmzTrackExporter.KMZ_EXTENSION);
|
||||
newMetaData.setMimeType(KMZ_MIME_TYPE);
|
||||
newMetaData.setParents(parents);
|
||||
|
||||
FileContent fileContent = new FileContent(KMZ_MIME_TYPE, file);
|
||||
return drive.files().insert(newMetaData, fileContent).execute();
|
||||
} catch (UserRecoverableAuthIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
if (canRetry) {
|
||||
return insertDriveFile(drive, folderId, trackName, file, false);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a drive file using info from a track. Returns true if successful.
|
||||
*
|
||||
* @param drive the drive
|
||||
* @param driveFile the drive file
|
||||
* @param context the context
|
||||
* @param myTracksProviderUtils the myTracksProviderUtils
|
||||
* @param track the track
|
||||
* @param canRetry true if can retry
|
||||
*/
|
||||
public static boolean updateDriveFile(Drive drive, File driveFile, Context context,
|
||||
MyTracksProviderUtils myTracksProviderUtils, Track track, boolean canRetry)
|
||||
throws IOException {
|
||||
Log.d(TAG, "Update drive file for track " + track.getName());
|
||||
java.io.File file = null;
|
||||
|
||||
try {
|
||||
file = SyncUtils.getTempFile(context, myTracksProviderUtils, track, true);
|
||||
if (file == null) {
|
||||
Log.e(TAG, "Unable to update drive file. File is null for track " + track.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
String title = track.getName() + "." + KmzTrackExporter.KMZ_EXTENSION;
|
||||
File updatedFile = updateDriveFile(drive, driveFile, title, file, canRetry);
|
||||
|
||||
if (updatedFile == null) {
|
||||
Log.e(
|
||||
TAG, "Unable to update drive file. Updated file is null for track " + track.getName());
|
||||
return false;
|
||||
}
|
||||
long modifiedTime = updatedFile.getModifiedDate().getValue();
|
||||
if (track.getModifiedTime() != modifiedTime) {
|
||||
track.setModifiedTime(modifiedTime);
|
||||
myTracksProviderUtils.updateTrack(track);
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
if (file != null) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a drive file using a track file.
|
||||
*
|
||||
* @param drive the drive
|
||||
* @param driveFile the drive file
|
||||
* @param driveTitle the drive title
|
||||
* @param file the track file. If null, just update the driveFile meta data
|
||||
* @param canRetry true if can retry
|
||||
*/
|
||||
public static File updateDriveFile(
|
||||
Drive drive, File driveFile, String driveTitle, java.io.File file, boolean canRetry)
|
||||
throws IOException {
|
||||
try {
|
||||
driveFile.setTitle(driveTitle);
|
||||
driveFile.setMimeType(KMZ_MIME_TYPE);
|
||||
|
||||
if (file != null) {
|
||||
FileContent fileContent = new FileContent(KMZ_MIME_TYPE, file);
|
||||
return drive.files().update(driveFile.getId(), driveFile, fileContent).execute();
|
||||
} else {
|
||||
return drive.files().update(driveFile.getId(), driveFile).execute();
|
||||
}
|
||||
} catch (UserRecoverableAuthIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
if (canRetry) {
|
||||
return updateDriveFile(drive, driveFile, driveTitle, file, false);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a temporary file for a track.
|
||||
*
|
||||
* @param context the context
|
||||
* @param myTracksProviderUtils the myMyTracksProviderUtils
|
||||
* @param track the track
|
||||
* @param useKmz true to output kmz
|
||||
*/
|
||||
public static java.io.File getTempFile(
|
||||
Context context, MyTracksProviderUtils myTracksProviderUtils, Track track, boolean useKmz)
|
||||
throws FileNotFoundException {
|
||||
java.io.File directory = new java.io.File(context.getCacheDir(), FileUtils.TEMP_FILES_DIR);
|
||||
|
||||
if (!FileUtils.ensureDirectoryExists(directory)) {
|
||||
Log.d(TAG, "Unable to create " + directory.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
for (java.io.File file : directory.listFiles()) {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
Track[] tracks = new Track[] { track };
|
||||
String extension = useKmz ? KmzTrackExporter.KMZ_EXTENSION : TrackFileFormat.KML.getExtension();
|
||||
java.io.File file = new java.io.File(
|
||||
directory, FileUtils.buildUniqueFileName(directory, track.getName(), extension));
|
||||
FileTrackExporter fileTrackExporter = new FileTrackExporter(myTracksProviderUtils, tracks,
|
||||
TrackFileFormat.KML.newTrackWriter(context, false, false), null);
|
||||
TrackExporter trackExporter = useKmz ? new KmzTrackExporter(
|
||||
myTracksProviderUtils, fileTrackExporter, tracks, context)
|
||||
: fileTrackExporter;
|
||||
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(file);
|
||||
if (trackExporter.writeTrack(fileOutputStream)) {
|
||||
return file;
|
||||
} else {
|
||||
if (!file.delete()) {
|
||||
Log.d(TAG, "Unable to delete file for track " + track.getName());
|
||||
}
|
||||
Log.d(TAG, "Unable to get file for track " + track.getName());
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to close file output stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a track with info from a drive file.
|
||||
*
|
||||
* @param myTracksProviderUtils the myTracksProviderUtils
|
||||
* @param track the track
|
||||
* @param driveFile the drive file
|
||||
*/
|
||||
public static void updateTrack(
|
||||
MyTracksProviderUtils myTracksProviderUtils, Track track, File driveFile) {
|
||||
track.setDriveId(driveFile != null ? driveFile.getId() : "");
|
||||
track.setModifiedTime(driveFile != null ? driveFile.getModifiedDate().getValue() : -1L);
|
||||
track.setSharedWithMe(driveFile != null ? driveFile.getSharedWithMeDate() != null : false);
|
||||
track.setSharedOwner(driveFile != null && driveFile.getSharedWithMeDate() != null
|
||||
&& driveFile.getOwnerNames().size() > 0 ? driveFile.getOwnerNames().get(0)
|
||||
: "");
|
||||
myTracksProviderUtils.updateTrack(track);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -16,16 +16,16 @@
|
||||
|
||||
package com.google.android.apps.mytracks.maps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
|
||||
/**
|
||||
* A dynamic speed path descriptor.
|
||||
|
||||
+3
-3
@@ -15,15 +15,15 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.maps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.android.gms.maps.model.Polyline;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
+4
-4
@@ -16,18 +16,18 @@
|
||||
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import com.google.android.apps.mytracks.widgets.TrackWidgetProvider;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.widgets.TrackWidgetProvider;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
/**
|
||||
* A service to control starting and stopping of a recording. This service,
|
||||
* through the AndroidManifest.xml, is configured to only allow components of
|
||||
|
||||
+1
-7
@@ -27,12 +27,11 @@ import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.os.Process;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.util.Log;
|
||||
@@ -67,15 +66,10 @@ import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackNameUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
|
||||
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
|
||||
import com.google.android.gms.location.ActivityRecognitionClient;
|
||||
import com.google.android.gms.location.DetectedActivity;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationResult;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
+10
-10
@@ -16,22 +16,22 @@
|
||||
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
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.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
-99
@@ -1,99 +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.services.tasks;
|
||||
|
||||
import com.google.android.gms.auth.GoogleAuthException;
|
||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An async task to check permission.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class CheckPermissionAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
public interface CheckPermissionCaller {
|
||||
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent);
|
||||
}
|
||||
|
||||
private static final String TAG = CheckPermissionAsyncTask.class.getSimpleName();
|
||||
|
||||
private Activity activity;
|
||||
private final String accountName;
|
||||
private final String scope;
|
||||
|
||||
/**
|
||||
* True if the AsyncTask result is success.
|
||||
*/
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* User recoverable intent if failed.
|
||||
*/
|
||||
private Intent userRecoverableIntent;
|
||||
|
||||
/**
|
||||
* True if the AsyncTask has completed.
|
||||
*/
|
||||
private boolean completed;
|
||||
|
||||
/**
|
||||
* True if can retry the AsyncTask.
|
||||
*/
|
||||
private boolean canRetry;
|
||||
|
||||
public CheckPermissionAsyncTask(Activity activity, String accountName, String scope) {
|
||||
this.activity = activity;
|
||||
this.accountName = accountName;
|
||||
this.scope = scope;
|
||||
success = false;
|
||||
userRecoverableIntent = null;
|
||||
completed = false;
|
||||
canRetry = true;
|
||||
}
|
||||
|
||||
public void setActivity(Activity activity) {
|
||||
this.activity = activity;
|
||||
if (completed && activity != null) {
|
||||
((CheckPermissionCaller) activity).onCheckPermissionDone(
|
||||
scope, success, userRecoverableIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
success = result;
|
||||
completed = true;
|
||||
if (activity != null) {
|
||||
((CheckPermissionCaller) activity).onCheckPermissionDone(
|
||||
scope, success, userRecoverableIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
-3
@@ -17,7 +17,6 @@
|
||||
package com.google.android.apps.mytracks.settings;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
@@ -198,8 +197,6 @@ public class AdvancedSettingsActivity extends AbstractSettingsActivity {
|
||||
// Actually wipe preferences and save synchronously
|
||||
sharedPreferences.edit().clear().commit();
|
||||
|
||||
SyncUtils.disableSync(AdvancedSettingsActivity.this);
|
||||
|
||||
// Give UI feedback in the UI thread
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
|
||||
+9
-158
@@ -16,88 +16,33 @@
|
||||
|
||||
package com.google.android.apps.mytracks.settings;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
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.CheckPermissionCaller;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* An activity for accessing settings.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SettingsActivity extends AbstractSettingsActivity implements CheckPermissionCaller {
|
||||
|
||||
private static final int DIALOG_NO_ACCOUNT = 0;
|
||||
private static final int DIALOG_CHOOSE_ACCOUNT = 1;
|
||||
private static final int DIALOG_CONFIRM_DRIVE_SYNC_ON = 2;
|
||||
|
||||
private static final int DRIVE_REQUEST_CODE = 0;
|
||||
|
||||
private CheckBoxPreference syncDrivePreference;
|
||||
private CheckPermissionAsyncTask syncDriveAsyncTask;
|
||||
public class SettingsActivity extends AbstractSettingsActivity {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
Object retained = getLastNonConfigurationInstance();
|
||||
if (retained instanceof CheckPermissionAsyncTask) {
|
||||
syncDriveAsyncTask = (CheckPermissionAsyncTask) retained;
|
||||
syncDriveAsyncTask.setActivity(this);
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
|
||||
syncDrivePreference = (CheckBoxPreference) findPreference(getString(R.string.drive_sync_key));
|
||||
syncDrivePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if ((Boolean) newValue) {
|
||||
Account[] accounts = AccountManager.get(SettingsActivity.this)
|
||||
.getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
if (accounts.length == 0) {
|
||||
PreferencesUtils.setString(SettingsActivity.this, R.string.google_account_key,
|
||||
PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
handleSync(false);
|
||||
showDialog(DIALOG_NO_ACCOUNT);
|
||||
} else if (accounts.length == 1) {
|
||||
PreferencesUtils.setString(
|
||||
SettingsActivity.this, R.string.google_account_key, accounts[0].name);
|
||||
showDialog(DIALOG_CONFIRM_DRIVE_SYNC_ON);
|
||||
} else {
|
||||
showDialog(DIALOG_CHOOSE_ACCOUNT);
|
||||
}
|
||||
} else {
|
||||
PreferencesUtils.setString(SettingsActivity.this, R.string.google_account_key,
|
||||
PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
handleSync(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
updateSyncDriveSummary();
|
||||
|
||||
configPreference(R.string.settings_map_key, MapSettingsActivity.class);
|
||||
configPreference(R.string.settings_chart_key, ChartSettingsActivity.class);
|
||||
configPreference(R.string.settings_stats_key, StatsSettingsActivity.class);
|
||||
@@ -106,100 +51,6 @@ public class SettingsActivity extends AbstractSettingsActivity implements CheckP
|
||||
configPreference(R.string.settings_advanced_key, AdvancedSettingsActivity.class);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
if (syncDriveAsyncTask != null) {
|
||||
syncDriveAsyncTask.setActivity(null);
|
||||
}
|
||||
return syncDriveAsyncTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id, Bundle bundle) {
|
||||
final Dialog dialog;
|
||||
switch (id) {
|
||||
case DIALOG_NO_ACCOUNT:
|
||||
dialog = new AlertDialog.Builder(this).setMessage(R.string.send_google_no_account_message)
|
||||
.setTitle(R.string.send_google_no_account_title)
|
||||
.setPositiveButton(R.string.generic_ok, null).create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
|
||||
@Override
|
||||
public void onShow(DialogInterface dialogInterface) {
|
||||
DialogUtils.setDialogTitleDivider(SettingsActivity.this, dialog);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
dialog = null;
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
|
||||
if (id == DIALOG_CONFIRM_DRIVE_SYNC_ON) {
|
||||
AlertDialog alertDialog = (AlertDialog) dialog;
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
this, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
alertDialog.setMessage(getString(R.string.sync_drive_confirm_message, googleAccount,
|
||||
getString(R.string.my_tracks_app_name)));
|
||||
}
|
||||
super.onPrepareDialog(id, dialog, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
|
||||
syncDriveAsyncTask = null;
|
||||
if (success) {
|
||||
onDrivePermissionSuccess();
|
||||
} else {
|
||||
if (userRecoverableIntent != null) {
|
||||
startActivityForResult(userRecoverableIntent, DRIVE_REQUEST_CODE);
|
||||
} else {
|
||||
onDrivePermissionFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onDrivePermissionSuccess() {
|
||||
handleSync(true);
|
||||
}
|
||||
|
||||
private void onDrivePermissionFailure() {
|
||||
Toast.makeText(
|
||||
SettingsActivity.this, R.string.send_google_no_account_permission, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles sync.
|
||||
*
|
||||
* @param value true to sync
|
||||
*/
|
||||
private void handleSync(boolean value) {
|
||||
syncDrivePreference.setChecked(value);
|
||||
updateSyncDriveSummary();
|
||||
|
||||
if (value) {
|
||||
SyncUtils.enableSync(this);
|
||||
} else {
|
||||
SyncUtils.disableSync(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates UI by account.
|
||||
*/
|
||||
private void updateSyncDriveSummary() {
|
||||
String googleAccount = PreferencesUtils.getString(
|
||||
this, R.string.google_account_key, PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
boolean hasAccount = !PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT.equals(googleAccount);
|
||||
syncDrivePreference.setSummaryOn(
|
||||
hasAccount ? getString(R.string.settings_google_drive_sync_summary_on, googleAccount) : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a preference by starting a new activity when it is clicked.
|
||||
*
|
||||
|
||||
+5
-5
@@ -16,16 +16,16 @@
|
||||
|
||||
package com.google.android.apps.mytracks.stats;
|
||||
|
||||
import static com.google.android.apps.mytracks.services.TrackRecordingService.MAX_NO_MOVEMENT_SPEED;
|
||||
import static com.google.android.apps.mytracks.services.TrackRecordingService.PAUSE_LATITUDE;
|
||||
import android.location.Location;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.util.CalorieUtils;
|
||||
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
import static com.google.android.apps.mytracks.services.TrackRecordingService.MAX_NO_MOVEMENT_SPEED;
|
||||
import static com.google.android.apps.mytracks.services.TrackRecordingService.PAUSE_LATITUDE;
|
||||
|
||||
/**
|
||||
* Updater for {@link TripStatistics}. For updating track trip statistics as new
|
||||
|
||||
@@ -1,75 +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.util;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
/**
|
||||
* Utilities for account.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class AccountUtils {
|
||||
|
||||
private AccountUtils() {}
|
||||
|
||||
/**
|
||||
* Sets up account spinner.
|
||||
*
|
||||
* @param fragmentActivity tyhe fragment activity
|
||||
* @param spinner the spinner
|
||||
* @param accounts the accounts
|
||||
*/
|
||||
public static void setupAccountSpinner(
|
||||
FragmentActivity fragmentActivity, Spinner spinner, Account[] accounts) {
|
||||
if (accounts.length > 1) {
|
||||
String shareTrackAccount = PreferencesUtils.getString(fragmentActivity,
|
||||
R.string.share_track_account_key, PreferencesUtils.SHARE_TRACK_ACCOUNT_DEFAULT);
|
||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
|
||||
fragmentActivity, R.layout.account_spinner_item);
|
||||
int selection = 0;
|
||||
for (int i = 0; i < accounts.length; i++) {
|
||||
String name = accounts[i].name;
|
||||
adapter.add(name);
|
||||
if (name.equals(shareTrackAccount)) {
|
||||
selection = i;
|
||||
}
|
||||
}
|
||||
adapter.setDropDownViewResource(R.layout.account_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
spinner.setSelection(selection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the share track account preference.
|
||||
*
|
||||
* @param context the context
|
||||
* @param account the account
|
||||
*/
|
||||
public static void updateShareTrackAccountPreference(Context context, Account account) {
|
||||
if (account != null) {
|
||||
PreferencesUtils.setString(context, R.string.share_track_account_key, account.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
|
||||
/**
|
||||
* Utilities for EULA.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class EulaUtils {
|
||||
|
||||
private static final String EULA_PREFERENCE_FILE = "eula";
|
||||
|
||||
// Accepting Google mobile terms of service
|
||||
private static final String ACCEPTED_EULA_PREFERENCE_KEY = "eula.google_mobile_tos_accepted";
|
||||
private static final String SHOW_ENABLE_SYNC_PREFERENCE_KEY = "showEnableSync";
|
||||
|
||||
private EulaUtils() {}
|
||||
|
||||
/**
|
||||
* Returns true if has accepted eula.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static boolean hasAcceptedEula(Context context) {
|
||||
return getValue(context, ACCEPTED_EULA_PREFERENCE_KEY, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets to true accepted eula.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void setAcceptedEula(Context context) {
|
||||
setValue(context, ACCEPTED_EULA_PREFERENCE_KEY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if should show enable sync.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static boolean showEnableSync(Context context) {
|
||||
return getValue(context, SHOW_ENABLE_SYNC_PREFERENCE_KEY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets to false show enable sync.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void setShowEnableSync(Context context) {
|
||||
setValue(context, SHOW_ENABLE_SYNC_PREFERENCE_KEY, false);
|
||||
}
|
||||
|
||||
private static boolean getValue(Context context, String key, boolean defaultValue) {
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
EULA_PREFERENCE_FILE, Context.MODE_PRIVATE);
|
||||
return sharedPreferences.getBoolean(key, defaultValue);
|
||||
}
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
private static void setValue(Context context, String key, boolean value) {
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
EULA_PREFERENCE_FILE, Context.MODE_PRIVATE);
|
||||
Editor editor = sharedPreferences.edit();
|
||||
editor.putBoolean(key, value);
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +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.util;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utilities for Google Earth.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class GoogleEarthUtils {
|
||||
|
||||
private static final String TAG = GoogleEarthUtils.class.getSimpleName();
|
||||
|
||||
private static final String GOOGLE_EARTH_CLASS = "com.google.earth.EarthActivity";
|
||||
private static final int GOOGLE_EARTH_MIN_VERSION_CODE = 13246120;
|
||||
private static final String GOOGLE_EARTH_PACKAGE = "com.google.earth";
|
||||
private static final String
|
||||
GOOGLE_EARTH_TOUR_FEATURE_ID = "com.google.earth.EXTRA.tour_feature_id";
|
||||
|
||||
public static final String GOOGLE_EARTH_MARKET_URL = "market://details?id="
|
||||
+ GOOGLE_EARTH_PACKAGE;
|
||||
|
||||
public static final String TOUR_FEATURE_ID_VALUE = "tour";
|
||||
|
||||
private GoogleEarthUtils() {}
|
||||
|
||||
/**
|
||||
* Returns true if Google Earth is installed.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static boolean isEarthInstalled(Context context) {
|
||||
List<ResolveInfo> infos = context.getPackageManager().queryIntentActivities(
|
||||
new Intent().setType(SyncUtils.KMZ_MIME_TYPE), PackageManager.MATCH_DEFAULT_ONLY);
|
||||
for (ResolveInfo info : infos) {
|
||||
if (info.activityInfo != null && info.activityInfo.packageName != null
|
||||
&& info.activityInfo.packageName.equals(GOOGLE_EARTH_PACKAGE)) {
|
||||
try {
|
||||
PackageInfo packageInfo = context.getPackageManager()
|
||||
.getPackageInfo(info.activityInfo.packageName, 0);
|
||||
return packageInfo.versionCode >= GOOGLE_EARTH_MIN_VERSION_CODE;
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(TAG, "Unable to get google earth package info", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an intent to play a kml file in Google Earth.
|
||||
*
|
||||
* @param kmlFilePath the kml file path
|
||||
*/
|
||||
public static Intent getPlayInEarthIntent(Context context, String kmlFilePath) {
|
||||
Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(MyTracksProviderUtils.AUTHORITY).path(kmlFilePath).build();
|
||||
context.grantUriPermission(GOOGLE_EARTH_PACKAGE, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
return new Intent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
.putExtra(GOOGLE_EARTH_TOUR_FEATURE_ID, TOUR_FEATURE_ID_VALUE)
|
||||
.setClassName(GOOGLE_EARTH_PACKAGE, GOOGLE_EARTH_CLASS)
|
||||
.setDataAndType(uri, SyncUtils.KMZ_MIME_TYPE);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +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.util;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Utilities for Google Feedback.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class GoogleFeedbackUtils {
|
||||
|
||||
private static final String TAG = GoogleFeedbackUtils.class.getSimpleName();
|
||||
|
||||
private GoogleFeedbackUtils() {}
|
||||
|
||||
/**
|
||||
* Binds the Google Feedback service.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public static void bindFeedback(Context context) {
|
||||
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
|
||||
ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
try {
|
||||
service.transact(Binder.FIRST_CALL_TRANSACTION, Parcel.obtain(), null, 0);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {}
|
||||
};
|
||||
// Bind to the service after creating it if necessary
|
||||
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
}
|
||||
@@ -61,20 +61,11 @@ public class PreferencesUtils {
|
||||
|
||||
public static final String DEFAULT_ACTIVITY_DEFAULT = "";
|
||||
|
||||
public static final String DRIVE_DELETED_LIST_DEFAULT = "";
|
||||
public static final String DRIVE_EDITED_LIST_DEFAULT = "";
|
||||
public static final long DRIVE_LARGEST_CHANGE_ID_DEFAULT = -1L;
|
||||
public static final boolean DRIVE_SYNC_DEFAULT = false;
|
||||
|
||||
public static final String EXPORT_EXTERNAL_STORAGE_FORMAT_DEFAULT = TrackFileFormat.KML.name();
|
||||
public static final boolean EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT = false;
|
||||
public static final boolean EXPORT_GOOGLE_MAPS_PUBLIC_DEFAULT = false;
|
||||
public static final String EXPORT_TYPE_DEFAULT = ExportType.GOOGLE_DRIVE.name();
|
||||
|
||||
|
||||
// Value for split_frequency_key and voice_frequency_key
|
||||
public static final int FREQUENCY_OFF = 0;
|
||||
|
||||
public static final String GOOGLE_ACCOUNT_DEFAULT = "";
|
||||
public static final int MAP_TYPE_DEFAUlT = 1;
|
||||
public static final int MAX_RECORDING_DISTANCE_DEFAULT = 200;
|
||||
|
||||
@@ -93,14 +84,8 @@ public class PreferencesUtils {
|
||||
|
||||
public static final long RECORDING_TRACK_ID_DEFAULT = -1L;
|
||||
public static final boolean RECORDING_TRACK_PAUSED_DEFAULT = true;
|
||||
public static final long SELECTED_TRACK_ID_DEFAULT = -1L;
|
||||
public static final String SENSOR_TYPE_DEFAULT = "NONE";
|
||||
|
||||
// Share track
|
||||
public static final String SHARE_TRACK_ACCOUNT_DEFAULT = "";
|
||||
public static final boolean SHARE_TRACK_INVITE_DEFAULT = false;
|
||||
public static final boolean SHARE_TRACK_PUBLIC_DEFAULT = false;
|
||||
|
||||
public static final int SPLIT_FREQUENCY_DEFAULT = 0;
|
||||
|
||||
// Stats
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Address;
|
||||
import android.location.Geocoder;
|
||||
import android.location.Location;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
@@ -63,12 +63,5 @@ public class TrackUtils {
|
||||
CalorieUtils.updateTrackCalorie(context, track);
|
||||
}
|
||||
}
|
||||
|
||||
boolean driveSync = PreferencesUtils.getBoolean(
|
||||
context, R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
|
||||
if (driveSync) {
|
||||
PreferencesUtils.addToList(context, R.string.drive_edited_list_key,
|
||||
PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT, String.valueOf(track.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:ellipsize="marquee"
|
||||
android:id="@android:id/text1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingLeft="8dp"
|
||||
android:singleLine="true"
|
||||
style="@style/TextSmall" />
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical" >
|
||||
<ScrollView style="@style/ScrollView.WithBottomButtons" >
|
||||
<WebView
|
||||
android:id="@+id/help_webview"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent" />
|
||||
</ScrollView>
|
||||
<View style="@style/BottomButtonDivider" />
|
||||
<LinearLayout style="@style/BottomButtonBar" >
|
||||
<Button
|
||||
android:id="@+id/help_feedback"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/menu_feedback"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
style="@style/BottomButton" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/map_container"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" >
|
||||
<TextView
|
||||
android:background="@color/holo_orange_dark"
|
||||
android:drawableLeft="@drawable/ic_warning"
|
||||
android:gravity="left|center_vertical"
|
||||
android:id="@+id/map_message"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:visibility="gone"
|
||||
style="@style/TextMedium.WithIcon" />
|
||||
<ImageButton
|
||||
android:background="@drawable/my_location"
|
||||
android:contentDescription="@string/image_my_location"
|
||||
android:id="@+id/map_my_location"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="wrap_content" />
|
||||
</RelativeLayout>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014 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.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<!-- android:icon="@drawable/ic_menu_feedback" -->
|
||||
<item
|
||||
android:id="@+id/help_play_store"
|
||||
android:title="@string/menu_help_play_store"/>
|
||||
<item
|
||||
android:id="@+id/help_eula"
|
||||
android:title="@string/menu_help_eula"/>
|
||||
<item
|
||||
android:id="@+id/help_forum"
|
||||
android:title="@string/menu_help_forum"/>
|
||||
</menu>
|
||||
@@ -15,11 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_play"
|
||||
android:id="@+id/list_context_menu_play"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/menu_play"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_share"
|
||||
android:id="@+id/list_context_menu_share"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_map_layer"
|
||||
android:id="@+id/menu_map_layer"
|
||||
android:orderInCategory="7"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/menu_map_layer">
|
||||
</item>
|
||||
</menu>
|
||||
@@ -27,12 +27,6 @@ limitations under the License.
|
||||
android:orderInCategory="2"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/menu_insert_photo"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_play"
|
||||
android:id="@+id/track_detail_play"
|
||||
android:orderInCategory="3"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/menu_play"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_share"
|
||||
android:id="@+id/track_detail_share"
|
||||
@@ -44,12 +38,6 @@ limitations under the License.
|
||||
android:id="@+id/track_detail_markers"
|
||||
android:orderInCategory="5"
|
||||
android:title="@string/menu_markers"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_play_multiple"
|
||||
android:id="@+id/track_detail_play_multiple"
|
||||
android:orderInCategory="6"
|
||||
android:title="@string/menu_play_multiple"/>
|
||||
<!-- android:orderInCategory="7" is in map.xml -->
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_export"
|
||||
android:id="@+id/track_detail_export"
|
||||
|
||||
@@ -26,14 +26,6 @@ limitations under the License.
|
||||
android:id="@+id/track_list_start_gps"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/menu_start_gps"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_play_multiple"
|
||||
android:id="@+id/track_list_play_mutliple"
|
||||
android:title="@string/menu_play_multiple"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_sync_now"
|
||||
android:id="@+id/track_list_sync_now"
|
||||
android:title="@string/menu_sync_now"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_aggregated_statistics"
|
||||
android:id="@+id/track_list_aggregated_statistics"
|
||||
@@ -54,8 +46,4 @@ limitations under the License.
|
||||
android:icon="@drawable/ic_menu_settings"
|
||||
android:id="@+id/track_list_settings"
|
||||
android:title="@string/menu_settings"/>
|
||||
<item
|
||||
android:icon="@drawable/ic_menu_help_feedback"
|
||||
android:id="@+id/track_list_help_feedback"
|
||||
android:title="@string/menu_help_feedback"/>
|
||||
</menu>
|
||||
@@ -1195,12 +1195,6 @@ limitations under the License.
|
||||
Character limit: ~20 (1 line)">
|
||||
Play
|
||||
</string>
|
||||
<string name="menu_play_multiple"
|
||||
translation_description="In the menu, to play multiple tracks together.
|
||||
|
||||
Character limit: ~20 (1 line)">
|
||||
Play multiple
|
||||
</string>
|
||||
<string name="menu_satellite"
|
||||
translation_description="In the menu, under the map layer option, the submenu to display
|
||||
satellite.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:contentAuthority="com.google.android.maps.mytracks"
|
||||
android:accountType="com.google"
|
||||
android:userVisible="true"
|
||||
android:supportsUploading="true" />
|
||||
-4
@@ -162,9 +162,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
if (!cursor.isNull(iconIndex)) {
|
||||
track.setIcon(cursor.getString(iconIndex));
|
||||
}
|
||||
if (!cursor.isNull(driveIdIndex)) {
|
||||
track.setDriveId(cursor.getString(driveIdIndex));
|
||||
}
|
||||
if (!cursor.isNull(modifiedTimeIndex)) {
|
||||
track.setModifiedTime(cursor.getLong(modifiedTimeIndex));
|
||||
}
|
||||
@@ -340,7 +337,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
values.put(TracksColumns.MINGRADE, tripStatistics.getMinGrade());
|
||||
values.put(TracksColumns.MAXGRADE, tripStatistics.getMaxGrade());
|
||||
values.put(TracksColumns.ICON, track.getIcon());
|
||||
values.put(TracksColumns.DRIVEID, track.getDriveId());
|
||||
values.put(TracksColumns.MODIFIEDTIME, track.getModifiedTime());
|
||||
values.put(TracksColumns.SHAREDWITHME, track.isSharedWithMe());
|
||||
values.put(TracksColumns.SHAREDOWNER, track.getSharedOwner());
|
||||
|
||||
@@ -45,7 +45,6 @@ public class Track implements Parcelable {
|
||||
*/
|
||||
private int numberOfPoints = 0;
|
||||
private String icon = "";
|
||||
private String driveId = "";
|
||||
private long modifiedTime = -1L;
|
||||
private boolean sharedWithMe = false;
|
||||
private String sharedOwner = "";
|
||||
@@ -66,7 +65,6 @@ public class Track implements Parcelable {
|
||||
stopId = in.readLong();
|
||||
numberOfPoints = in.readInt();
|
||||
icon = in.readString();
|
||||
driveId = in.readString();
|
||||
modifiedTime = in.readLong();
|
||||
sharedWithMe = in.readByte() == 1;
|
||||
sharedOwner = in.readString();
|
||||
@@ -95,7 +93,6 @@ public class Track implements Parcelable {
|
||||
dest.writeLong(stopId);
|
||||
dest.writeInt(numberOfPoints);
|
||||
dest.writeString(icon);
|
||||
dest.writeString(driveId);
|
||||
dest.writeLong(modifiedTime);
|
||||
dest.writeByte((byte) (sharedWithMe ? 1 : 0));
|
||||
dest.writeString(sharedOwner);
|
||||
@@ -182,14 +179,6 @@ public class Track implements Parcelable {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getDriveId() {
|
||||
return driveId;
|
||||
}
|
||||
|
||||
public void setDriveId(String driveId) {
|
||||
this.driveId = driveId;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user