merge heads

This commit is contained in:
Jimmy Shih
2012-10-25 14:19:06 -07:00
23 changed files with 190 additions and 377 deletions
+1 -2
View File
@@ -4,8 +4,7 @@ applications that wish to use these files should consult the appropriate
licenses or the JAR's authors. licenses or the JAR's authors.
Android Support Package: Android Support Package:
android-support-v4-r7-googlemaps.jar android-support-v4.jar
- see https://github.com/petedoyle/android-support-v4-googlemaps
Ant+: Ant+:
antlib.jar - see http://www.thisisant.com/pages/developer-zone/android-api antlib.jar - see http://www.thisisant.com/pages/developer-zone/android-api
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -18,12 +18,12 @@ limitations under the License.
<!-- Total distance --> <!-- Total distance -->
<TableRow> <TableRow>
<TextView <TextView
android:text="@string/stats_total_distance" android:text="@string/stats_distance"
style="@style/StatsLabel" /> style="@style/StatsLabel" />
</TableRow> </TableRow>
<TableRow> <TableRow>
<TextView <TextView
android:id="@+id/stats_total_distance_value" android:id="@+id/stats_distance_value"
style="@style/StatsValue" /> style="@style/StatsValue" />
</TableRow> </TableRow>
<!-- Total time/moving time --> <!-- Total time/moving time -->
+2 -2
View File
@@ -2226,8 +2226,8 @@ limitations under the License.
Character limit: ~23 (1 line)"> Character limit: ~23 (1 line)">
Speed Speed
</string> </string>
<string name="stats_total_distance" <string name="stats_distance"
translation_description="In the 'Stats' page, the total distance."> translation_description="In the 'Stats' page, the distance.">
Distance Distance
</string> </string>
<string name="stats_total_time" <string name="stats_total_time"
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.services.RemoveTempFilesService; import com.google.android.apps.mytracks.services.RemoveTempFilesService;
import com.google.android.apps.mytracks.util.AnalyticsUtils;
import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.maps.mytracks.BuildConfig; import com.google.android.maps.mytracks.BuildConfig;
@@ -36,8 +35,6 @@ public class MyTracksApplication extends Application {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
ApiAdapterFactory.getApiAdapter().enableStrictMode(); ApiAdapterFactory.getApiAdapter().enableStrictMode();
} }
AnalyticsUtils.sendPageViews(getApplicationContext(), "/appstart");
AnalyticsUtils.dispatch();
Intent intent = new Intent(this, RemoveTempFilesService.class); Intent intent = new Intent(this, RemoveTempFilesService.class);
startService(intent); startService(intent);
} }
@@ -218,6 +218,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
trackDataHub.start(); trackDataHub.start();
AnalyticsUtils.sendPageViews(this, "/page/track_detail");
} }
@Override @Override
@@ -416,6 +416,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
trackDataHub.start(); trackDataHub.start();
AnalyticsUtils.sendPageViews(this, "/page/track_list");
} }
@Override @Override
@@ -1,43 +0,0 @@
/*
* Copyright 2011 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.backup;
import android.annotation.TargetApi;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Implementation of {@link BackupPreferencesListener} that calls the
* {@link BackupManager}. <br>
* For API Level 8 or higher.
*
* @author Jimmy Shih
*/
@TargetApi(8)
public class Api8BackupPreferencesListener implements BackupPreferencesListener {
private final BackupManager backupManager;
public Api8BackupPreferencesListener(Context context) {
this.backupManager = new BackupManager(context);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
backupManager.dataChanged();
}
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010 Google Inc. * Copyright 2011 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
@@ -15,13 +15,26 @@
*/ */
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
/** /**
* Shared preferences listener which notifies the backup system about new data * Backup preference listener.
* being available for backup.
* *
* @author Rodrigo Damazio * @author Jimmy Shih
*/ */
public interface BackupPreferencesListener extends OnSharedPreferenceChangeListener { public class BackupPreferencesListener implements OnSharedPreferenceChangeListener {
}
private final BackupManager backupManager;
public BackupPreferencesListener(Context context) {
this.backupManager = new BackupManager(context);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
backupManager.dataChanged();
}
}
@@ -25,12 +25,15 @@ import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import android.content.Context; import android.content.Context;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener; import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.telephony.PhoneStateListener; import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
/** /**
@@ -49,8 +52,24 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
private static final String TAG = AnnouncementPeriodicTask.class.getSimpleName(); private static final String TAG = AnnouncementPeriodicTask.class.getSimpleName();
private static final long HOUR_TO_MILLISECOND = 60 * 60 * 1000; private static final long HOUR_TO_MILLISECOND = 60 * 60 * 1000;
private static final HashMap<String, String> SPEECH_PARAMS = new HashMap<String, String>();
static {
SPEECH_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "not_used");
}
private final OnUtteranceCompletedListener
utteranceListener = new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
int result = audioManager.abandonAudioFocus(null);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "Failed to relinquish audio focus.");
}
}
};
private final Context context; private final Context context;
protected TextToSpeech tts; private TextToSpeech tts;
// Response from TTS after its initialization // Response from TTS after its initialization
private int initStatus = TextToSpeech.ERROR; private int initStatus = TextToSpeech.ERROR;
@@ -61,6 +80,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
// True if speech is allowed // True if speech is allowed
private boolean speechAllowed; private boolean speechAllowed;
private final AudioManager audioManager;
/** /**
* Listener which updates {@link #speechAllowed} when the phone state changes. * Listener which updates {@link #speechAllowed} when the phone state changes.
*/ */
@@ -77,6 +98,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
public AnnouncementPeriodicTask(Context context) { public AnnouncementPeriodicTask(Context context) {
this.context = context; this.context = context;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
} }
@Override @Override
@@ -146,7 +168,7 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
/** /**
* Called when TTS is ready. * Called when TTS is ready.
*/ */
protected void onTtsReady() { private void onTtsReady() {
Locale locale = Locale.getDefault(); Locale locale = Locale.getDefault();
int languageAvailability = tts.isLanguageAvailable(locale); int languageAvailability = tts.isLanguageAvailable(locale);
if (languageAvailability == TextToSpeech.LANG_MISSING_DATA if (languageAvailability == TextToSpeech.LANG_MISSING_DATA
@@ -163,6 +185,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
// Slow down the speed just a bit as it is hard to hear when exercising. // Slow down the speed just a bit as it is hard to hear when exercising.
tts.setSpeechRate(TTS_SPEECH_RATE); tts.setSpeechRate(TTS_SPEECH_RATE);
tts.setOnUtteranceCompletedListener(utteranceListener);
} }
/** /**
@@ -170,8 +194,18 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
* *
* @param announcement the announcement * @param announcement the announcement
*/ */
protected void speakAnnouncement(String announcement) { private void speakAnnouncement(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null); int result = audioManager.requestAudioFocus(
null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "Failed to request audio focus.");
}
/*
* We don't care about the utterance id. It is supplied here to force
* onUtteranceCompleted to be called.
*/
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, SPEECH_PARAMS);
} }
/** /**
@@ -224,8 +258,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
String totalDistance = context.getResources() String totalDistance = context.getResources()
.getQuantityString(totalDistanceId, getQuantityCount(distance), distance); .getQuantityString(totalDistanceId, getQuantityCount(distance), distance);
return context.getString(R.string.voice_template, totalDistance, getAnnounceTime( return context.getString(R.string.voice_template, totalDistance,
tripStatistics.getMovingTime()), rate); getAnnounceTime(tripStatistics.getMovingTime()), rate);
} }
/** /**
@@ -15,8 +15,6 @@
*/ */
package com.google.android.apps.mytracks.services.tasks; package com.google.android.apps.mytracks.services.tasks;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import android.content.Context; import android.content.Context;
/** /**
@@ -28,6 +26,6 @@ public class AnnouncementPeriodicTaskFactory implements PeriodicTaskFactory {
@Override @Override
public PeriodicTask create(Context context) { public PeriodicTask create(Context context) {
return ApiAdapterFactory.getApiAdapter().getAnnouncementPeriodicTask(context); return new AnnouncementPeriodicTask(context);
} }
} }
@@ -1,81 +0,0 @@
/*
* Copyright 2011 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 android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.util.Log;
import java.util.HashMap;
/**
* This class will periodically announce the user's trip statistics. This class
* will request and release audio focus.
*
* @author Sandor Dornbush
*/
@TargetApi(8)
public class Api8AnnouncementPeriodicTask extends AnnouncementPeriodicTask {
private static final String TAG = Api8AnnouncementPeriodicTask.class.getSimpleName();
private static final HashMap<String, String> SPEECH_PARAMS = new HashMap<String, String>();
static {
SPEECH_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "not_used");
}
private final OnUtteranceCompletedListener
utteranceListener = new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
int result = audioManager.abandonAudioFocus(null);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "Failed to relinquish audio focus.");
}
}
};
private final AudioManager audioManager;
public Api8AnnouncementPeriodicTask(Context context) {
super(context);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@Override
protected void onTtsReady() {
super.onTtsReady();
tts.setOnUtteranceCompletedListener(utteranceListener);
}
@Override
protected synchronized void speakAnnouncement(String announcement) {
int result = audioManager.requestAudioFocus(
null, TextToSpeech.Engine.DEFAULT_STREAM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "Failed to request audio focus.");
}
/*
* We don't care about the utterance id. It is supplied here to force
* onUtteranceCompleted to be called.
*/
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, SPEECH_PARAMS);
}
}
@@ -52,8 +52,8 @@ public class AbstractSettingsActivity extends PreferenceActivity {
preferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE); preferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE);
// Set up automatic preferences backup // Set up automatic preferences backup
backupPreferencesListener = ApiAdapterFactory.getApiAdapter() backupPreferencesListener = new BackupPreferencesListener(this);
.getBackupPreferencesListener(this);
preferenceManager.getSharedPreferences() preferenceManager.getSharedPreferences()
.registerOnSharedPreferenceChangeListener(backupPreferencesListener); .registerOnSharedPreferenceChangeListener(backupPreferencesListener);
} }
@@ -119,9 +119,4 @@ public class Api11Adapter extends Api10Adapter {
public void invalidMenu(Activity activity) { public void invalidMenu(Activity activity) {
activity.invalidateOptionsMenu(); activity.invalidateOptionsMenu();
} }
@Override
public void disableHardwareAccelerated(View view) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
} }
@@ -1,165 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.ContextualActionModeCallback;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
import com.google.android.apps.mytracks.services.sensors.BluetoothConnectionManager;
import com.google.android.apps.mytracks.services.tasks.AnnouncementPeriodicTask;
import com.google.android.apps.mytracks.services.tasks.PeriodicTask;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.apache.ApacheHttpTransport;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* API level 7 specific implementation of the {@link ApiAdapter}.
*
* @author Bartlomiej Niechwiej
*/
public class Api7Adapter implements ApiAdapter {
@Override
public PeriodicTask getAnnouncementPeriodicTask(Context context) {
return new AnnouncementPeriodicTask(context);
}
@Override
public BackupPreferencesListener getBackupPreferencesListener(Context context) {
return new BackupPreferencesListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// Do nothing
}
};
}
@Override
public void applyPreferenceChanges(Editor editor) {
editor.commit();
}
@Override
public void enableStrictMode() {
// Not supported
}
@Override
public byte[] copyByteArray(byte[] input, int start, int end) {
int length = end - start;
byte[] output = new byte[length];
System.arraycopy(input, start, output, 0, length);
return output;
}
@Override
public HttpTransport getHttpTransport() {
return new ApacheHttpTransport();
}
@Override
public boolean isGeoCoderPresent() {
return true;
}
@Override
public BluetoothSocket getBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException {
try {
Class<? extends BluetoothDevice> c = bluetoothDevice.getClass();
Method insecure = c.getMethod("createInsecureRfcommSocket", Integer.class);
insecure.setAccessible(true);
return (BluetoothSocket) insecure.invoke(bluetoothDevice, 1);
} catch (SecurityException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (NoSuchMethodException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (IllegalArgumentException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (IllegalAccessException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (InvocationTargetException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
}
return bluetoothDevice.createRfcommSocketToServiceRecord(BluetoothConnectionManager.MY_TRACKS_UUID);
}
@Override
public void hideTitle(Activity activity) {
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
@Override
public void configureActionBarHomeAsUp(Activity activity) {
// Do nothing
}
@Override
public void configureListViewContextualMenu(Activity activity, ListView listView,
ContextualActionModeCallback contextualActionModeCallback) {
activity.registerForContextMenu(listView);
}
@Override
public void configureSearchWidget(Activity activity, MenuItem menuItem) {
// Do nothing
}
@Override
public boolean handleSearchMenuSelection(Activity activity) {
activity.onSearchRequested();
return true;
}
@Override
public <T> void addAllToArrayAdapter(ArrayAdapter<T> arrayAdapter, List<T> items) {
for (T item : items) {
arrayAdapter.add(item);
}
}
@Override
public void invalidMenu(Activity activity) {
// Do nothing
}
@Override
public void disableHardwareAccelerated(View view) {
// Do nothing
}
@Override
public boolean handleSearchKey(MenuItem menuItem) {
// Return false and allow the framework to handle the search key.
return false;
}
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012 Google Inc. * Copyright 2010 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
@@ -15,27 +15,125 @@
*/ */
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.io.backup.Api8BackupPreferencesListener; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; import com.google.android.apps.mytracks.ContextualActionModeCallback;
import com.google.android.apps.mytracks.services.tasks.Api8AnnouncementPeriodicTask; import com.google.android.apps.mytracks.services.sensors.BluetoothConnectionManager;
import com.google.android.apps.mytracks.services.tasks.PeriodicTask; import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.apache.ApacheHttpTransport;
import android.content.Context; import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import android.view.MenuItem;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/** /**
* API level 8 specific implementation of the {@link ApiAdapter}. * API level 8 specific implementation of the {@link ApiAdapter}.
* *
* @author Jimmy Shih * @author Bartlomiej Niechwiej
*/ */
public class Api8Adapter extends Api7Adapter { public class Api8Adapter implements ApiAdapter {
@Override @Override
public PeriodicTask getAnnouncementPeriodicTask(Context context) { public void applyPreferenceChanges(Editor editor) {
return new Api8AnnouncementPeriodicTask(context); editor.commit();
} }
@Override @Override
public BackupPreferencesListener getBackupPreferencesListener(Context context) { public void enableStrictMode() {
return new Api8BackupPreferencesListener(context); // Not supported
}
@Override
public byte[] copyByteArray(byte[] input, int start, int end) {
int length = end - start;
byte[] output = new byte[length];
System.arraycopy(input, start, output, 0, length);
return output;
}
@Override
public HttpTransport getHttpTransport() {
return new ApacheHttpTransport();
}
@Override
public boolean isGeoCoderPresent() {
return true;
}
@Override
public BluetoothSocket getBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException {
try {
Class<? extends BluetoothDevice> c = bluetoothDevice.getClass();
Method insecure = c.getMethod("createInsecureRfcommSocket", Integer.class);
insecure.setAccessible(true);
return (BluetoothSocket) insecure.invoke(bluetoothDevice, 1);
} catch (SecurityException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (NoSuchMethodException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (IllegalArgumentException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (IllegalAccessException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
} catch (InvocationTargetException e) {
Log.d(Constants.TAG, "Unable to create insecure connection", e);
}
return bluetoothDevice.createRfcommSocketToServiceRecord(BluetoothConnectionManager.MY_TRACKS_UUID);
}
@Override
public void hideTitle(Activity activity) {
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
@Override
public void configureActionBarHomeAsUp(Activity activity) {
// Do nothing
}
@Override
public void configureListViewContextualMenu(Activity activity, ListView listView,
ContextualActionModeCallback contextualActionModeCallback) {
activity.registerForContextMenu(listView);
}
@Override
public void configureSearchWidget(Activity activity, MenuItem menuItem) {
// Do nothing
}
@Override
public boolean handleSearchMenuSelection(Activity activity) {
activity.onSearchRequested();
return true;
}
@Override
public <T> void addAllToArrayAdapter(ArrayAdapter<T> arrayAdapter, List<T> items) {
for (T item : items) {
arrayAdapter.add(item);
}
}
@Override
public void invalidMenu(Activity activity) {
// Do nothing
}
@Override
public boolean handleSearchKey(MenuItem menuItem) {
// Return false and allow the framework to handle the search key.
return false;
} }
} }
@@ -16,17 +16,13 @@
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.ContextualActionModeCallback; import com.google.android.apps.mytracks.ContextualActionModeCallback;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
import com.google.android.apps.mytracks.services.tasks.PeriodicTask;
import com.google.api.client.http.HttpTransport; import com.google.api.client.http.HttpTransport;
import android.app.Activity; import android.app.Activity;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
@@ -41,24 +37,6 @@ import java.util.List;
*/ */
public interface ApiAdapter { public interface ApiAdapter {
/**
* Gets an announcement periodic task.
* <p>
* Due to changes in API level 8.
*
* @param context the context
*/
public PeriodicTask getAnnouncementPeriodicTask(Context context);
/**
* Gets a {@link BackupPreferencesListener}.
* <p>
* Due to changes in API level 8.
*
* @param context the context
*/
public BackupPreferencesListener getBackupPreferencesListener(Context context);
/** /**
* Applies all the changes done to a given preferences editor. Changes may or * Applies all the changes done to a given preferences editor. Changes may or
* may not be applied immediately. * may not be applied immediately.
@@ -184,15 +162,6 @@ public interface ApiAdapter {
*/ */
public void invalidMenu(Activity activity); public void invalidMenu(Activity activity);
/**
* Diables hardware-accelerated rendering for a view.
* <p>
* Due to chagnes in API level 11.
*
* @param view the view
*/
public void disableHardwareAccelerated(View view);
/** /**
* Handles the search key press. Returns true if handled. * Handles the search key press. Returns true if handled.
* <p> * <p>
@@ -43,11 +43,8 @@ public class ApiAdapterFactory {
} else if (Build.VERSION.SDK_INT >= 9) { } else if (Build.VERSION.SDK_INT >= 9) {
apiAdapter = new Api9Adapter(); apiAdapter = new Api9Adapter();
return apiAdapter; return apiAdapter;
} else if (Build.VERSION.SDK_INT >= 8) {
apiAdapter = new Api8Adapter();
return apiAdapter;
} else { } else {
apiAdapter = new Api7Adapter(); apiAdapter = new Api8Adapter();
return apiAdapter; return apiAdapter;
} }
} }
@@ -109,7 +109,7 @@ public class StatsUtils {
// Set total distance // Set total distance
double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance(); double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance();
setDistanceValue(activity, R.id.stats_total_distance_value, totalDistance, metricUnits); setDistanceValue(activity, R.id.stats_distance_value, totalDistance, metricUnits);
// Set total time // Set total time
setTimeValue(activity, R.id.stats_total_time_value, setTimeValue(activity, R.id.stats_total_time_value,
@@ -63,7 +63,7 @@ public class TrackWidgetConfigActivity extends Activity {
this, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT); this, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT);
List<CharSequence> list = new ArrayList<CharSequence>(); List<CharSequence> list = new ArrayList<CharSequence>();
addItem(list, R.string.stats_total_distance); addItem(list, R.string.stats_distance);
addItem(list, R.string.stats_total_time); addItem(list, R.string.stats_total_time);
addItem(list, reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); addItem(list, reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
addItem(list, R.string.stats_moving_time); addItem(list, R.string.stats_moving_time);
@@ -220,7 +220,7 @@ public class TrackWidgetProvider extends AppWidgetProvider {
boolean reportSpeed) { boolean reportSpeed) {
switch (value) { switch (value) {
case 0: case 0:
updateTotalDistance(context, remoteViews, ids, tripStatistics, metricUnits); updateDistance(context, remoteViews, ids, tripStatistics, metricUnits);
break; break;
case 1: case 1:
updateTotalTime(context, remoteViews, ids, tripStatistics, isRecording, isPaused); updateTotalTime(context, remoteViews, ids, tripStatistics, isRecording, isPaused);
@@ -236,7 +236,7 @@ public class TrackWidgetProvider extends AppWidgetProvider {
context, remoteViews, ids, tripStatistics, metricUnits, reportSpeed); context, remoteViews, ids, tripStatistics, metricUnits, reportSpeed);
break; break;
default: default:
updateTotalDistance(context, remoteViews, ids, tripStatistics, metricUnits); updateDistance(context, remoteViews, ids, tripStatistics, metricUnits);
break; break;
} }
@@ -271,7 +271,7 @@ public class TrackWidgetProvider extends AppWidgetProvider {
} }
/** /**
* Updates total distance. * Updates distance.
* *
* @param context the context * @param context the context
* @param remoteViews the remote views * @param remoteViews the remote views
@@ -279,11 +279,11 @@ public class TrackWidgetProvider extends AppWidgetProvider {
* @param tripStatistics the trip statistics * @param tripStatistics the trip statistics
* @param metricUnits true to use metric units * @param metricUnits true to use metric units
*/ */
private static void updateTotalDistance(Context context, RemoteViews remoteViews, int[] ids, private static void updateDistance(Context context, RemoteViews remoteViews, int[] ids,
TripStatistics tripStatistics, boolean metricUnits) { TripStatistics tripStatistics, boolean metricUnits) {
double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance(); double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance();
String[] totalDistanceParts = StringUtils.getDistanceParts(context, totalDistance, metricUnits); String[] totalDistanceParts = StringUtils.getDistanceParts(context, totalDistance, metricUnits);
remoteViews.setTextViewText(ids[0], context.getString(R.string.stats_total_distance)); remoteViews.setTextViewText(ids[0], context.getString(R.string.stats_distance));
remoteViews.setTextViewText(ids[1], totalDistanceParts[0]); remoteViews.setTextViewText(ids[1], totalDistanceParts[0]);
remoteViews.setTextViewText(ids[2], totalDistanceParts[1]); remoteViews.setTextViewText(ids[2], totalDistanceParts[1]);
} }
@@ -63,7 +63,7 @@ public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListAct
// Menu in TrackListActivity. // Menu in TrackListActivity.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_aggregated_statistics), EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_aggregated_statistics),
true); true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.stats_total_distance)); EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.stats_distance));
EndToEndTestUtils.SOLO.goBack(); EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync(); instrumentation.waitForIdleSync();
EndToEndTestUtils.createTrackIfEmpty(1, false); EndToEndTestUtils.createTrackIfEmpty(1, false);