Merge heads

This commit is contained in:
youtaol
2013-04-17 19:51:58 +08:00
parent 3d6f9a1a2d
commit d66bf7b395
93 changed files with 840 additions and 734 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ limitations under the License.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="65" android:versionCode="66"
android:versionName="2.0.4" android:versionName="2.0.4"
package="com.google.android.maps.mytracks" > package="com.google.android.maps.mytracks" >
<!-- Permission to initialize services --> <!-- Permission to initialize services -->
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18,6 +18,8 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment; import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment;
import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment.AddEmailsCaller; import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment.AddEmailsCaller;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment.CheckPermissionCaller;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment; import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller; import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller;
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment; import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment;
@@ -27,7 +29,6 @@ import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity
import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants; import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants;
import com.google.android.apps.mytracks.io.maps.ChooseMapActivity; import com.google.android.apps.mytracks.io.maps.ChooseMapActivity;
import com.google.android.apps.mytracks.io.maps.SendMapsActivity; import com.google.android.apps.mytracks.io.maps.SendMapsActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.PermissionCallback;
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils; import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
@@ -47,6 +48,7 @@ import android.app.Activity;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@@ -58,91 +60,58 @@ import java.io.IOException;
* @author Jimmy Shih * @author Jimmy Shih
*/ */
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity
implements ChooseAccountCaller, AddEmailsCaller, ChooseActivityCaller { implements ChooseAccountCaller, CheckPermissionCaller, AddEmailsCaller, ChooseActivityCaller {
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName(); private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
private static final String SEND_REQUEST_KEY = "send_request_key";
private SendRequest sendRequest; private SendRequest sendRequest;
private PermissionCallback driveCallback = new PermissionCallback() {
@Override
public void onSuccess() {
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
}
@Override
public void onFailure() {
handleNoAccountPermission();
}
};
private PermissionCallback mapsCallback = new PermissionCallback() {
@Override
public void onSuccess() {
checkFusionTablesPermission();
}
@Override
public void onFailure() {
handleNoAccountPermission();
}
};
private PermissionCallback fusionTablesCallback = new PermissionCallback() {
@Override
public void onSuccess() {
checkSpreadsheetPermission();
}
@Override
public void onFailure() {
handleNoAccountPermission();
}
};
private PermissionCallback spreadsheetsCallback = new PermissionCallback() {
@Override
public void onSuccess() {
startNextActivity();
}
@Override
public void onFailure() {
handleNoAccountPermission();
}
};
public void sendToGoogle(SendRequest request) { public void sendToGoogle(SendRequest request) {
sendRequest = request; sendRequest = request;
new ChooseAccountDialogFragment().show( new ChooseAccountDialogFragment().show(
getSupportFragmentManager(), ChooseAccountDialogFragment.CHOOSE_ACCOUNT_DIALOG_TAG); getSupportFragmentManager(), ChooseAccountDialogFragment.CHOOSE_ACCOUNT_DIALOG_TAG);
} }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
sendRequest = savedInstanceState.getParcelable(SEND_REQUEST_KEY);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(SEND_REQUEST_KEY, sendRequest);
}
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE: case SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE:
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID); SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
driveCallback.onSuccess(); onDrivePermissionSuccess();
} else { } else {
driveCallback.onFailure(); onPermissionFailure();
} }
break; break;
case SendToGoogleUtils.FUSION_TABLES_PERMISSION_REQUEST_CODE: case SendToGoogleUtils.FUSION_TABLES_PERMISSION_REQUEST_CODE:
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.FUSION_TABLES_NOTIFICATION_ID); SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.FUSION_TABLES_NOTIFICATION_ID);
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
fusionTablesCallback.onSuccess(); onFusionTablesSuccess();
} else { } else {
fusionTablesCallback.onFailure(); onPermissionFailure();
} }
break; break;
case SendToGoogleUtils.SPREADSHEET_PERMISSION_REQUEST_CODE: case SendToGoogleUtils.SPREADSHEET_PERMISSION_REQUEST_CODE:
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.SPREADSHEET_NOTIFICATION_ID); SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.SPREADSHEET_NOTIFICATION_ID);
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
spreadsheetsCallback.onSuccess(); onSpreadsheetsPermissionSuccess();
} else { } else {
spreadsheetsCallback.onFailure(); onPermissionFailure();
} }
break; break;
default: default:
@@ -157,7 +126,53 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
return; return;
} }
sendRequest.setAccount(new Account(googleAccount, Constants.ACCOUNT_TYPE)); sendRequest.setAccount(new Account(googleAccount, Constants.ACCOUNT_TYPE));
checkDrivePermission();
// Check Drive permission
boolean needDrivePermission = sendRequest.isSendDrive();
if (!needDrivePermission) {
boolean defaultTablePublic = PreferencesUtils.getBoolean(
this, R.string.default_table_public_key, PreferencesUtils.DEFAULT_TABLE_PUBLIC_DEFAULT);
needDrivePermission = defaultTablePublic && sendRequest.isSendFusionTables();
}
if (!needDrivePermission) {
needDrivePermission = sendRequest.isSendSpreadsheets();
}
if (needDrivePermission) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.DRIVE_SCOPE);
getSupportFragmentManager()
.beginTransaction().add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
} else {
onDrivePermissionSuccess();
}
}
@Override
public void onCheckPermissionDone(String scope, boolean success, Intent intent) {
if (success) {
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
onDrivePermissionSuccess();
} else if (scope.equals(SendToGoogleUtils.FUSION_TABLES_SCOPE)) {
onFusionTablesSuccess();
} else {
onSpreadsheetsPermissionSuccess();
}
} else {
if (intent != null) {
int requestCode;
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
requestCode = SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE;
} else if (scope.equals(SendToGoogleUtils.FUSION_TABLES_SCOPE)) {
requestCode = SendToGoogleUtils.FUSION_TABLES_PERMISSION_REQUEST_CODE;
} else {
requestCode = SendToGoogleUtils.SPREADSHEET_PERMISSION_REQUEST_CODE;
}
startActivityForResult(intent, requestCode);
} else {
onPermissionFailure();
}
}
} }
@Override @Override
@@ -182,111 +197,92 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
} }
} }
/** private void onDrivePermissionSuccess() {
* Checks the Drive permission. // Check Maps permission
*/ if (sendRequest.isSendMaps()) {
private void checkDrivePermission() { AccountManager.get(this).getAuthToken(
boolean needDrivePermission = sendRequest.isSendDrive(); sendRequest.getAccount(), MapsConstants.SERVICE_NAME, null, this,
if (!needDrivePermission) {
boolean defaultTablePublic = PreferencesUtils.getBoolean(
this, R.string.default_table_public_key, PreferencesUtils.DEFAULT_TABLE_PUBLIC_DEFAULT);
needDrivePermission = defaultTablePublic && sendRequest.isSendFusionTables();
}
if (!needDrivePermission) {
needDrivePermission = sendRequest.isSendSpreadsheets();
}
if (needDrivePermission) {
SendToGoogleUtils.checkPermissionByActivity(this, sendRequest.getAccount().name,
SendToGoogleUtils.DRIVE_SCOPE, SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE,
driveCallback);
} else {
driveCallback.onSuccess();
}
}
/**
* Checks the Fusion Tables permission.
*/
private void checkFusionTablesPermission() {
if (sendRequest.isSendFusionTables()) {
SendToGoogleUtils.checkPermissionByActivity(this, sendRequest.getAccount().name,
SendToGoogleUtils.FUSION_TABLES_SCOPE,
SendToGoogleUtils.FUSION_TABLES_PERMISSION_REQUEST_CODE, fusionTablesCallback);
} else {
fusionTablesCallback.onSuccess();
}
}
/**
* Checks the Spreadsheet permission.
*/
private void checkSpreadsheetPermission() {
if (sendRequest.isSendSpreadsheets()) {
SendToGoogleUtils.checkPermissionByActivity(this, sendRequest.getAccount().name,
SendToGoogleUtils.SPREADSHEET_SCOPE,
SendToGoogleUtils.SPREADSHEET_PERMISSION_REQUEST_CODE, spreadsheetsCallback);
} else {
spreadsheetsCallback.onSuccess();
}
}
/**
* Gets the user permission to access a service.
*
* @param authTokenType the auth token type of the service
* @param needPermission true if need the permission
* @param callback callback after getting the permission
*/
private void getPermission(
String authTokenType, boolean needPermission, final PermissionCallback callback) {
if (needPermission) {
AccountManager.get(this).getAuthToken(sendRequest.getAccount(), authTokenType, null, this,
new AccountManagerCallback<Bundle>() { new AccountManagerCallback<Bundle>() {
@Override @Override
public void run(AccountManagerFuture<Bundle> future) { public void run(AccountManagerFuture<Bundle> future) {
try { try {
if (future.getResult().getString(AccountManager.KEY_AUTHTOKEN) != null) { if (future.getResult().getString(AccountManager.KEY_AUTHTOKEN) != null) {
callback.onSuccess(); runOnUiThread(new Runnable() {
@Override
public void run() {
onMapsPermissionSuccess();
}
});
return;
} else { } else {
Log.d(TAG, "auth token is null"); Log.d(TAG, "auth token is null");
callback.onFailure();
} }
} catch (OperationCanceledException e) { } catch (OperationCanceledException e) {
Log.d(TAG, "Unable to get auth token", e); Log.d(TAG, "Unable to get auth token", e);
callback.onFailure();
} catch (AuthenticatorException e) { } catch (AuthenticatorException e) {
Log.d(TAG, "Unable to get auth token", e); Log.d(TAG, "Unable to get auth token", e);
callback.onFailure();
} catch (IOException e) { } catch (IOException e) {
Log.d(TAG, "Unable to get auth token", e); Log.d(TAG, "Unable to get auth token", e);
callback.onFailure();
} }
runOnUiThread(new Runnable() {
@Override
public void run() {
onPermissionFailure();
}
});
} }
}, null); }, null);
} else { } else {
callback.onSuccess(); onMapsPermissionSuccess();
}
}
private void onMapsPermissionSuccess() {
// Check Fusion Tables permission
if (sendRequest.isSendFusionTables()) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.FUSION_TABLES_SCOPE);
getSupportFragmentManager()
.beginTransaction().add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
} else {
onFusionTablesSuccess();
}
}
private void onFusionTablesSuccess() {
// Check Spreadsheets permission
if (sendRequest.isSendSpreadsheets()) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.SPREADSHEET_SCOPE);
getSupportFragmentManager()
.beginTransaction().add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
} else {
onSpreadsheetsPermissionSuccess();
} }
} }
/** /**
* Starts the next activity. If * On spreadsheets permission success. If
* <p> * <p>
* sendDrive -> {@link SendDriveActivity} * isSendDrive and isDriveEnableSync -> enable sync
* <p> * <p>
* sendMaps and newMap -> {@link SendMapsActivity} * isSendDrive and isDriveShare -> show {@link AddEmailsDialogFragment}
* <p> * <p>
* sendMaps and !newMap -> {@link ChooseMapActivity} * isSendDrive -> start {@link SendDriveActivity}
* <p> * <p>
* !sendMaps && sendFusionTables -> {@link SendFusionTablesActivity} * isSendMaps and isMapShare -> show {@link ChooseActivityDialogFragment}
* <p> * <p>
* !sendMaps && !sendFusionTables && sendSpreadsheets -> * isSendMaps and isMapsExistingMap -> start {@link ChooseMapActivity}
* {@link SendSpreadsheetsActivity}
* <p> * <p>
* !sendMaps && !sendFusionTables && !sendSpreadsheets -> * isSendMaps and !isMapsExistingMap -> {@link SendMapsActivity}
* {@link UploadResultActivity} * <p>
* isSendFusionTables -> start {@link SendFusionTablesActivity}
* <p>
* isSendSpreadsheets -> start {@link SendSpreadsheetsActivity}
* <p>
* else -> start {@link UploadResultActivity}
*/ */
private void startNextActivity() { private void onSpreadsheetsPermissionSuccess() {
Class<?> next; Class<?> next;
if (sendRequest.isSendDrive()) { if (sendRequest.isSendDrive()) {
if (sendRequest.isDriveEnableSync()) { if (sendRequest.isDriveEnableSync()) {
@@ -328,9 +324,9 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
} }
/** /**
* Handles when not able to get account permission. * Call when not able to get permission for a google service.
*/ */
private void handleNoAccountPermission() { private void onPermissionFailure() {
Toast.makeText(this, R.string.send_google_no_account_permission, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.send_google_no_account_permission, Toast.LENGTH_LONG).show();
} }
} }
@@ -92,7 +92,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
// From intent // From intent
private long trackId; private long trackId;
private long markerId; private long markerId;
private Track track;
// Preferences // Preferences
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
@@ -299,10 +298,12 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
menu.findItem(R.id.track_detail_save_tcx) menu.findItem(R.id.track_detail_save_tcx)
.setTitle(getString(R.string.menu_save_format, fileTypes[3])); .setTitle(getString(R.string.menu_save_format, fileTypes[3]));
menu.findItem(R.id.track_detail_edit).setVisible(!track.isSharedWithMe()); Track track = myTracksProviderUtils.getTrack(trackId);
boolean sharedWithMe = track != null ? track.isSharedWithMe() : true;
menu.findItem(R.id.track_detail_edit).setVisible(!sharedWithMe);
shareDriveMenuItem = menu.findItem(R.id.track_detail_share_drive); shareDriveMenuItem = menu.findItem(R.id.track_detail_share_drive);
shareDriveMenuItem.setEnabled(!track.isSharedWithMe()); shareDriveMenuItem.setEnabled(!sharedWithMe);
shareDriveMenuItem.setVisible(!track.isSharedWithMe()); shareDriveMenuItem.setVisible(!sharedWithMe);
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker); insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
playMenuItem = menu.findItem(R.id.track_detail_play); playMenuItem = menu.findItem(R.id.track_detail_play);
@@ -377,7 +378,9 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
return true; return true;
case R.id.track_detail_send_google: case R.id.track_detail_send_google:
AnalyticsUtils.sendPageViews(this, "/action/send_google"); AnalyticsUtils.sendPageViews(this, "/action/send_google");
ChooseUploadServiceDialogFragment.newInstance(track.isSharedWithMe()).show( Track track = myTracksProviderUtils.getTrack(trackId);
boolean sharedWithMe = track != null ? track.isSharedWithMe() : true;
ChooseUploadServiceDialogFragment.newInstance(sharedWithMe).show(
getSupportFragmentManager(), getSupportFragmentManager(),
ChooseUploadServiceDialogFragment.CHOOSE_UPLOAD_SERVICE_DIALOG_TAG); ChooseUploadServiceDialogFragment.CHOOSE_UPLOAD_SERVICE_DIALOG_TAG);
return true; return true;
@@ -518,6 +521,7 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L);
if (markerId != -1L) { if (markerId != -1L) {
// Use the trackId from the marker
Waypoint waypoint = myTracksProviderUtils.getWaypoint(markerId); Waypoint waypoint = myTracksProviderUtils.getWaypoint(markerId);
if (waypoint == null) { if (waypoint == null) {
finish(); finish();
@@ -529,8 +533,16 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
finish(); finish();
return; return;
} }
track = myTracksProviderUtils.getTrack(trackId); Track track = myTracksProviderUtils.getTrack(trackId);
if (track == null) { if (track == null) {
// Use the last track if markerId is not set
if (markerId == -1L) {
track = myTracksProviderUtils.getLastTrack();
if (track != null) {
trackId = track.getId();
return;
}
}
finish(); finish();
return; return;
} }
@@ -587,7 +599,8 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
if (isRecording) { if (isRecording) {
title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording); title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording);
} else { } else {
title = track.getName(); Track track = myTracksProviderUtils.getTrack(trackId);
title = track != null ? track.getName() : "";
} }
setTitle(title); setTitle(title);
} }
@@ -47,7 +47,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity
public static final String EXTRA_NEW_TRACK = "new_track"; public static final String EXTRA_NEW_TRACK = "new_track";
private static final String TAG = TrackEditActivity.class.getSimpleName(); private static final String TAG = TrackEditActivity.class.getSimpleName();
private static final String ICON_VALUE = "icon_value"; private static final String ICON_VALUE_KEY = "icon_value_key";
private Long trackId; private Long trackId;
private MyTracksProviderUtils myTracksProviderUtils; private MyTracksProviderUtils myTracksProviderUtils;
@@ -115,7 +115,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity
iconValue = null; iconValue = null;
if (bundle != null) { if (bundle != null) {
iconValue = bundle.getString(ICON_VALUE); iconValue = bundle.getString(ICON_VALUE_KEY);
} }
if (iconValue == null) { if (iconValue == null) {
iconValue = track.getIcon(); iconValue = track.getIcon();
@@ -164,7 +164,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putString(ICON_VALUE, iconValue); outState.putString(ICON_VALUE_KEY, iconValue);
} }
@Override @Override
@@ -0,0 +1,126 @@
/*
* 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.io.sendtogoogle.SendToGoogleUtils;
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.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import java.io.IOException;
/**
* A non UI fragment to check permission.
*
* @author Jimmy Shih
*/
public class CheckPermissionFragment extends Fragment {
/**
* Interface for caller of this fragment.
*
* @author Jimmy Shih
*/
public interface CheckPermissionCaller {
/**
* Called when check permission is done.
*
* @param scope the permission scope
* @param success true if success
* @param intent if not success, intent to prompt for permission
*/
public void onCheckPermissionDone(String scope, boolean success, Intent intent);
}
public static final String CHECK_PERMISSION_TAG = "checkPermission";
private static final String TAG = CheckPermissionFragment.class.getSimpleName();
private static final String KEY_ACCOUNT_NAME = "accountName";
private static final String KEY_SCOPE = "scope";
private CheckPermissionCaller caller;
public static CheckPermissionFragment newInstance(String accountName, String scope) {
Bundle bundle = new Bundle();
bundle.putString(KEY_ACCOUNT_NAME, accountName);
bundle.putString(KEY_SCOPE, scope);
CheckPermissionFragment checkPermissionFragment = new CheckPermissionFragment();
checkPermissionFragment.setArguments(bundle);
return checkPermissionFragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
caller = (CheckPermissionCaller) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() + " must implement " + CheckPermissionCaller.class.getSimpleName());
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Only want one instance
setRetainInstance(true);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
String accountName = getArguments().getString(KEY_ACCOUNT_NAME);
String scope = getArguments().getString(KEY_SCOPE);
try {
SendToGoogleUtils.getGoogleAccountCredential(getActivity(), accountName, scope);
finish(scope, true, null);
} catch (UserRecoverableAuthException e) {
finish(scope, false, e.getIntent());
} catch (GoogleAuthException e) {
Log.e(TAG, "GoogleAuthException", e);
finish(scope, false, null);
} catch (UserRecoverableAuthIOException e) {
finish(scope, false, e.getIntent());
} catch (IOException e) {
Log.e(TAG, "IOException", e);
finish(scope, false, null);
}
}
});
thread.start();
}
private void finish(final String scope, final boolean success, final Intent intent) {
getFragmentManager().popBackStack();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
caller.onCheckPermissionDone(scope, success, intent);
}
});
}
}
@@ -95,10 +95,31 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
// Current location // Current location
private Location currentLocation; private Location currentLocation;
// True to keep the currentLocation visible /**
* True to continue keeping the current location visible on the screen.
* <p>
* Set to true when <br>
* 1. user clicks on the my location button <br>
* Set to false when <br>
* 1. showing a marker <br>
* 2. user manually zooms/pans
*/
private boolean keepCurrentLocationVisible; private boolean keepCurrentLocationVisible;
// True to zoom to currentLocation when it is available /**
* True to zoom/center the current location when it is available.
* <p>
* Set to true when <br>
* 1. user clicks on the my location button <br>
* 2. first location during a recording <br>
* Set to false when <br>
* 1. showing a marker <br>
* 2. user manually zooms/pans <br>
* 3. after zooming to the current location <br>
* <p>
* The last one is to support the use case of zooming only once. After zoom,
* set it to false. E.g., only zoom to the first location during a recording.
*/
private boolean zoomToCurrentLocation; private boolean zoomToCurrentLocation;
private OnLocationChangedListener onLocationChangedListener; private OnLocationChangedListener onLocationChangedListener;
@@ -221,8 +242,8 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
keepCurrentLocationVisible = savedInstanceState.getBoolean( keepCurrentLocationVisible = savedInstanceState.getBoolean(
KEEP_CURRENT_LOCATION_VISIBLE_KEY, false); KEEP_CURRENT_LOCATION_VISIBLE_KEY, false);
zoomToCurrentLocation = savedInstanceState.getBoolean(ZOOM_TO_CURRENT_LOCATION_KEY, false); zoomToCurrentLocation = savedInstanceState.getBoolean(ZOOM_TO_CURRENT_LOCATION_KEY, false);
currentLocation = (Location) savedInstanceState.getParcelable(CURRENT_LOCATION_KEY); Location location = (Location) savedInstanceState.getParcelable(CURRENT_LOCATION_KEY);
updateCurrentLocation(); setCurrentLocation(location);
} }
} }
@@ -236,6 +257,7 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
ApiAdapterFactory.getApiAdapter().invalidMenu(getActivity()); ApiAdapterFactory.getApiAdapter().invalidMenu(getActivity());
} }
resumeTrackDataHub(); resumeTrackDataHub();
updateCurrentLocation();
} }
@Override @Override
@@ -348,7 +370,7 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
} }
boolean myLocationEnabled = true; boolean myLocationEnabled = true;
if (state == LocationState.DISABLED) { if (state == LocationState.DISABLED) {
currentLocation = null; setCurrentLocation(null);
myLocationEnabled = false; myLocationEnabled = false;
} }
googleMap.setMyLocationEnabled(myLocationEnabled); googleMap.setMyLocationEnabled(myLocationEnabled);
@@ -415,10 +437,7 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
@Override @Override
public void onLocationChanged(final Location location) { public void onLocationChanged(final Location location) {
if (isResumed()) { if (isResumed()) {
if (isSelectedTrackRecording() && currentLocation == null && location != null) { setCurrentLocation(location);
zoomToCurrentLocation = true;
}
currentLocation = location;
updateCurrentLocation(); updateCurrentLocation();
} }
} }
@@ -586,6 +605,19 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
} }
} }
/**
* Sets the current location.
*
* @param location the location
*/
private void setCurrentLocation(Location location) {
// If recording, zoom to the first location
if (isSelectedTrackRecording() && currentLocation == null && location != null) {
zoomToCurrentLocation = true;
}
currentLocation = location;
}
/** /**
* Updates the current location and zoom to it if necessary. * Updates the current location and zoom to it if necessary.
*/ */
@@ -684,12 +716,14 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
*/ */
private LatLng getDefaultLatLng() { private LatLng getDefaultLatLng() {
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity()); MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity());
Location location = myTracksProviderUtils.getLastValidTrackPoint(); Track track = myTracksProviderUtils.getLastTrack();
if (location != null) { if (track != null) {
return new LatLng(location.getLatitude(), location.getLongitude()); Location location = myTracksProviderUtils.getLastValidTrackPoint(track.getId());
} else { if (location != null) {
return new LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE); return new LatLng(location.getLatitude(), location.getLongitude());
}
} }
return new LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE);
} }
/** /**
@@ -1,35 +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.sendtogoogle;
/**
* A callback after getting the permission to access a Google service.
*
* @author Jimmy Shih
*/
public interface PermissionCallback {
/**
* To be invoked when the permission is granted.
*/
public void onSuccess();
/**
* To be invoked when the permission is not granted.
*/
public void onFailure();
}
@@ -20,15 +20,12 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.gms.auth.GoogleAuthException; import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.maps.mytracks.R; 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.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.DriveScopes;
import com.google.api.services.fusiontables.FusiontablesScopes; import com.google.api.services.fusiontables.FusiontablesScopes;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import android.app.Activity;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
@@ -174,55 +171,6 @@ public class SendToGoogleUtils {
return credential.getToken(); return credential.getToken();
} }
/**
* Checks permission by an activity. Will start an activity to request
* permission using the request code.
*
* @param activity the activity
* @param accountName the account name
* @param scope the scope
* @param requestCode the request code
* @param permissionCallback the permission callback
*/
public static void checkPermissionByActivity(final Activity activity, final String accountName,
final String scope, final int requestCode, final PermissionCallback permissionCallback) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
getGoogleAccountCredential(activity, accountName, scope);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
permissionCallback.onSuccess();
}
});
} catch (UserRecoverableAuthException e) {
activity.startActivityForResult(e.getIntent(), requestCode);
} catch (GoogleAuthException e) {
Log.e(TAG, "GoogleAuthException", e);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
permissionCallback.onFailure();
}
});
} catch (UserRecoverableAuthIOException e) {
activity.startActivityForResult(e.getIntent(), requestCode);
} catch (IOException e) {
Log.e(TAG, "IOException", e);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
permissionCallback.onFailure();
}
});
}
}
});
thread.start();
}
/** /**
* Sends a notification to request permission. * Sends a notification to request permission.
* *
@@ -17,12 +17,14 @@
package com.google.android.apps.mytracks.settings; package com.google.android.apps.mytracks.settings;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.io.sendtogoogle.PermissionCallback;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils; import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.io.sync.SyncUtils; import com.google.android.apps.mytracks.io.sync.SyncUtils;
import com.google.android.apps.mytracks.util.DialogUtils; import com.google.android.apps.mytracks.util.DialogUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
@@ -37,8 +39,10 @@ import android.preference.CheckBoxPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceChangeListener;
import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -49,24 +53,11 @@ import java.util.List;
*/ */
public class GoogleSettingsActivity extends AbstractSettingsActivity { public class GoogleSettingsActivity extends AbstractSettingsActivity {
private static final String TAG = GoogleSettingsActivity.class.getSimpleName();
private static final String ACCOUNT_NAME_KEY = "accountName"; private static final String ACCOUNT_NAME_KEY = "accountName";
private static final int DIALOG_CONFIRM_SWITCH_ACCOUNT = 0; private static final int DIALOG_CONFIRM_SWITCH_ACCOUNT = 0;
private static final int DIALOG_CONFIRM_DRIVE_SYNC_ON = 1; private static final int DIALOG_CONFIRM_DRIVE_SYNC_ON = 1;
private PermissionCallback permissionCallback = new PermissionCallback() {
@Override
public void onSuccess() {
handleSync(true);
}
@Override
public void onFailure() {
Toast.makeText(
GoogleSettingsActivity.this, R.string.send_google_no_account_message, Toast.LENGTH_LONG)
.show();
}
};
private ListPreference googleAccountPreference; private ListPreference googleAccountPreference;
private CheckBoxPreference driveSyncPreference; private CheckBoxPreference driveSyncPreference;
@@ -143,9 +134,9 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
case SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE: case SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE:
SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID); SendToGoogleUtils.cancelNotification(this, SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
permissionCallback.onSuccess(); onDrivePermissionSuccess();
} else { } else {
permissionCallback.onFailure(); onDrivePermissionFailure();
} }
break; break;
default: default:
@@ -167,12 +158,37 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface d, int button) { public void onClick(DialogInterface d, int button) {
String googleAccount = PreferencesUtils.getString( final String googleAccount = PreferencesUtils.getString(
GoogleSettingsActivity.this, R.string.google_account_key, GoogleSettingsActivity.this, R.string.google_account_key,
PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT); PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
SendToGoogleUtils.checkPermissionByActivity(GoogleSettingsActivity.this, /*
googleAccount, SendToGoogleUtils.DRIVE_SCOPE, * This class, a PreferenceActivity, needs to support api level
SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE, permissionCallback); * 8+, thus cannot use CheckPermissionFragment because a
* Fragment is only available for api level 11+ and there is no
* support library for PreferenceActivity.
*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
SendToGoogleUtils.getGoogleAccountCredential(
GoogleSettingsActivity.this, googleAccount,
SendToGoogleUtils.DRIVE_SCOPE);
handleDriveAccess(true, null);
} catch (UserRecoverableAuthException e) {
handleDriveAccess(false, e.getIntent());
} catch (GoogleAuthException e) {
Log.e(TAG, "GoogleAuthException", e);
handleDriveAccess(false, null);
} catch (UserRecoverableAuthIOException e) {
handleDriveAccess(false, e.getIntent());
} catch (IOException e) {
Log.e(TAG, "IOException", e);
handleDriveAccess(false, null);
}
}
});
thread.start();
} }
}); });
break; break;
@@ -182,6 +198,33 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
return dialog; return dialog;
} }
private void handleDriveAccess(final boolean success, final Intent intent) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (success) {
onDrivePermissionSuccess();
} else {
if (intent != null) {
startActivityForResult(intent, SendToGoogleUtils.DRIVE_PERMISSION_REQUEST_CODE);
} else {
onDrivePermissionFailure();
}
}
}
});
}
private void onDrivePermissionSuccess() {
handleSync(true);
}
private void onDrivePermissionFailure() {
Toast.makeText(
GoogleSettingsActivity.this, R.string.send_google_no_account_message, Toast.LENGTH_LONG)
.show();
}
@Override @Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle bundle) { protected void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
AlertDialog alertDialog = (AlertDialog) dialog; AlertDialog alertDialog = (AlertDialog) dialog;
@@ -86,7 +86,7 @@ public class TrackWidgetConfigActivity extends Activity {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance( AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(
TrackWidgetConfigActivity.this); TrackWidgetConfigActivity.this);
TrackWidgetProvider.updateAppWidget( TrackWidgetProvider.updateAppWidget(
TrackWidgetConfigActivity.this, appWidgetManager, appWidgetId); TrackWidgetConfigActivity.this, appWidgetManager, appWidgetId, -1L);
PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item1, PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item1,
item1.getSelectedItemPosition()); item1.getSelectedItemPosition());
PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item2, PreferencesUtils.setInt(TrackWidgetConfigActivity.this, R.string.track_widget_item2,
@@ -82,59 +82,53 @@ public class TrackWidgetProvider extends AppWidgetProvider {
|| context.getString(R.string.track_stopped_broadcast_action).equals(action) || context.getString(R.string.track_stopped_broadcast_action).equals(action)
|| context.getString(R.string.track_update_broadcast_action).equals(action)) { || context.getString(R.string.track_update_broadcast_action).equals(action)) {
long trackId = intent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L); long trackId = intent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L);
updateAllWidgets(context, trackId); updateAllAppWidgets(context, trackId);
} }
} }
@Override @Override
public void onEnabled(Context context) { public void onEnabled(Context context) {
// Need to update all widgets after phone reboot super.onEnabled(context);
updateAllWidgets(context, -1L); // Need to update all app widgets after phone reboot
updateAllAppWidgets(context, -1L);
} }
/** @Override
* Updates all widgets. public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
* super.onUpdate(context, appWidgetManager, appWidgetIds);
* @param context the context // Need to update all app widgets after software update
* @param trackId track id updateAllAppWidgets(context, -1L);
*/
private void updateAllWidgets(Context context, long trackId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, TrackWidgetProvider.class));
for (int appWidgetId : appWidgetIds) {
int size = ApiAdapterFactory.getApiAdapter().getAppWidgetSize(appWidgetManager, appWidgetId);
RemoteViews remoteViews = getRemoteViews(context, trackId, size);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
} }
@TargetApi(16) @TargetApi(16)
@Override @Override
public void onAppWidgetOptionsChanged( public void onAppWidgetOptionsChanged(
Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
if (newOptions != null) { if (newOptions != null) {
int size; int newSize;
if (newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1) if (newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1)
== AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) { == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) {
size = 1; newSize = 1;
} else { } else {
int height = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); int height = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
if (height == 0) { if (height == 0) {
size = 2; newSize = 2;
} else if (height >= FOUR_CELLS) { } else if (height >= FOUR_CELLS) {
size = 4; newSize = 4;
} else if (height >= THREE_CELLS) { } else if (height >= THREE_CELLS) {
size = 3; newSize = 3;
} else if (height >= TWO_CELLS) { } else if (height >= TWO_CELLS) {
size = 2; newSize = 2;
} else { } else {
size = 1; newSize = 1;
} }
} }
ApiAdapterFactory.getApiAdapter().setAppWidgetSize(appWidgetManager, appWidgetId, size); int size = ApiAdapterFactory.getApiAdapter().getAppWidgetSize(appWidgetManager, appWidgetId);
RemoteViews remoteViews = getRemoteViews(context, -1L, size); if (size != newSize) {
appWidgetManager.updateAppWidget(appWidgetId, remoteViews); ApiAdapterFactory.getApiAdapter().setAppWidgetSize(appWidgetManager, appWidgetId, newSize);
updateAppWidget(context, appWidgetManager, appWidgetId, -1L);
}
} }
} }
@@ -144,15 +138,30 @@ public class TrackWidgetProvider extends AppWidgetProvider {
* @param context the context * @param context the context
* @param appWidgetManager the app widget manager * @param appWidgetManager the app widget manager
* @param appWidgetId the app widget id * @param appWidgetId the app widget id
* @param trackId the track id. -1L to not specify one
*/ */
public static void updateAppWidget( public static void updateAppWidget(
Context context, AppWidgetManager appWidgetManager, int appWidgetId) { Context context, AppWidgetManager appWidgetManager, int appWidgetId, long trackId) {
int size = ApiAdapterFactory.getApiAdapter().getAppWidgetSize(appWidgetManager, appWidgetId); int size = ApiAdapterFactory.getApiAdapter().getAppWidgetSize(appWidgetManager, appWidgetId);
ApiAdapterFactory.getApiAdapter().setAppWidgetSize(appWidgetManager, appWidgetId, size); RemoteViews remoteViews = getRemoteViews(context, trackId, size);
RemoteViews remoteViews = getRemoteViews(context, -1L, size);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews); appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
} }
/**
* Updates all app widgets.
*
* @param context the context
* @param trackId track id
*/
private static void updateAllAppWidgets(Context context, long trackId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, TrackWidgetProvider.class));
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, trackId);
}
}
/** /**
* Gets the remote views. * Gets the remote views.
* *
@@ -252,11 +252,6 @@ public interface MyTracksProviderUtils {
*/ */
public Location getLastValidTrackPoint(long trackId); public Location getLastValidTrackPoint(long trackId);
/**
* Gets the last valid location recorded. Returns null if it doesn't exist.
*/
public Location getLastValidTrackPoint();
/** /**
* Creates a location cursor. The caller owns the returned cursor and is * Creates a location cursor. The caller owns the returned cursor and is
* responsible for closing it. * responsible for closing it.
@@ -238,9 +238,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
public Track getLastTrack() { public Track getLastTrack() {
Cursor cursor = null; Cursor cursor = null;
try { try {
String selection = TracksColumns._ID + "=(select max(" + TracksColumns._ID + ") from " // Using the same order as shown in the track list
+ TracksColumns.TABLE_NAME + ")"; cursor = getTrackCursor(null, null, null,
cursor = getTrackCursor(null, selection, null, TracksColumns._ID); TracksColumns.SHAREDWITHME + " ASC, " + TracksColumns.STARTTIME + " DESC");
if (cursor != null && cursor.moveToNext()) { if (cursor != null && cursor.moveToNext()) {
return createTrack(cursor); return createTrack(cursor);
} }
@@ -816,14 +816,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
return findTrackPointBy(selection, selectionArgs); return findTrackPointBy(selection, selectionArgs);
} }
@Override
public Location getLastValidTrackPoint() {
String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + ") from "
+ TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.LATITUDE + "<="
+ MAX_LATITUDE + ")";
return findTrackPointBy(selection, null);
}
@Override @Override
public Cursor getTrackPointCursor( public Cursor getTrackPointCursor(
long trackId, long startTrackPointId, int maxLocations, boolean descending) { long trackId, long startTrackPointId, int maxLocations, boolean descending) {