From da013e9d51f68b4479781e61b6c37b73477e3da6 Mon Sep 17 00:00:00 2001 From: Jimmy Shih Date: Fri, 27 Jan 2012 15:51:43 -0800 Subject: [PATCH] Clean up ApiAdapter now that we only support API 7 or greater. - rename ApiLevelAdapter to ApiAdapter - rename ApiFeatures to ApiAdapterFactory --- MyTracks/project.properties | 2 +- MyTracks/res/values/strings.xml | 7 - .../android/apps/mytracks/ChartActivity.java | 7 +- .../android/apps/mytracks/CheckUnits.java | 7 +- .../apps/mytracks/DeleteAllTracks.java | 4 +- .../android/apps/mytracks/DeleteTrack.java | 4 +- .../android/apps/mytracks/MapActivity.java | 7 +- .../android/apps/mytracks/MyTracks.java | 12 +- .../apps/mytracks/SettingsActivity.java | 48 +++---- .../android/apps/mytracks/StatsActivity.java | 7 +- .../mytracks/content/MyTracksProvider.java | 10 +- .../apps/mytracks/content/TrackDataHub.java | 4 +- .../io/backup/PreferenceBackupHelper.java | 4 +- .../sendtogoogle/AccountChooserActivity.java | 4 +- .../SendFusionTablesAsyncTask.java | 4 +- .../UploadServiceChooserActivity.java | 4 +- .../mytracks/services/PreferenceManager.java | 8 +- .../services/TrackRecordingService.java | 28 ++-- .../sensors/BluetoothConnectionManager.java | 38 +----- .../services/sensors/ZephyrMessageParser.java | 5 +- .../sensors/ant/AntDirectSensorManager.java | 4 +- .../ant/AntSrmBridgeSensorManager.java | 4 +- .../tasks/StatusAnnouncerFactory.java | 26 +--- .../apps/mytracks/util/Api10Adapter.java | 43 ++++++ ...ApiLevel3Adapter.java => Api7Adapter.java} | 70 ++++------ ...ApiLevel8Adapter.java => Api8Adapter.java} | 19 ++- ...ApiLevel9Adapter.java => Api9Adapter.java} | 19 ++- .../apps/mytracks/util/ApiAdapter.java | 105 +++++++++++++++ .../apps/mytracks/util/ApiAdapterFactory.java | 47 +++++++ .../apps/mytracks/util/ApiFeatures.java | 122 ------------------ .../apps/mytracks/util/ApiLevelAdapter.java | 113 ---------------- .../mytracks/util/BluetoothDeviceUtils.java | 22 +--- .../android/apps/mytracks/util/EulaUtil.java | 2 +- .../services/TestRecordingService.java | 64 +++++++++ .../services/TrackRecordingServiceTest.java | 21 +-- .../tasks/StatusAnnouncerFactoryTest.java | 62 +-------- .../mytracks/util/ApiAdapterFactoryTest.java | 24 +--- .../apps/mytracks/util/ApiFeaturesTest.java | 62 --------- 38 files changed, 410 insertions(+), 633 deletions(-) create mode 100644 MyTracks/src/com/google/android/apps/mytracks/util/Api10Adapter.java rename MyTracks/src/com/google/android/apps/mytracks/util/{ApiLevel3Adapter.java => Api7Adapter.java} (63%) rename MyTracks/src/com/google/android/apps/mytracks/util/{ApiLevel8Adapter.java => Api8Adapter.java} (50%) rename MyTracks/src/com/google/android/apps/mytracks/util/{ApiLevel9Adapter.java => Api9Adapter.java} (61%) create mode 100644 MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapter.java create mode 100644 MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapterFactory.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/util/ApiLevelAdapter.java create mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/TestRecordingService.java rename MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel5Adapter.java => MyTracksTest/src/com/google/android/apps/mytracks/util/ApiAdapterFactoryTest.java (51%) delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/util/ApiFeaturesTest.java diff --git a/MyTracks/project.properties b/MyTracks/project.properties index c946f8ad0..81cd85e3e 100644 --- a/MyTracks/project.properties +++ b/MyTracks/project.properties @@ -11,5 +11,5 @@ split.density=false proguard.config=proguard.cfg # Project target. -target=Google Inc.:Google APIs:15 +target=Google Inc.:Google APIs:7 android.library.reference.1=../MyTracksLib diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index ba3b892dd..13bef87cc 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -1716,13 +1716,6 @@ limitations under the License. Screenshot: settings_recording_top.png"> Voice - - Voice announcement is not available on your Android phone. - context = activity.getApplicationContext(); myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context); - HttpTransport transport = ApiFeatures.getInstance().getApiAdapter().getHttpTransport(); + HttpTransport transport = ApiAdapterFactory.getApiAdapter().getHttpTransport(); httpRequestFactory = transport.createRequestFactory(new MethodOverride()); canRetry = true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java index b6f3fc8d1..da27228bf 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.io.sendtogoogle; import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.maps.mytracks.R; import android.app.Activity; @@ -218,7 +218,7 @@ public class UploadServiceChooserActivity extends Activity { editor.putBoolean(getString(R.string.send_to_fusion_tables_key), sendFusionTables()); editor.putBoolean(getString(R.string.send_to_docs_key), sendDocs()); } - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java index 501fadf39..9e9c90a35 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.services; import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.maps.mytracks.R; import android.content.Context; @@ -174,19 +174,19 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener { public void setAutoResumeTrackCurrentRetry(int retryAttempts) { Editor editor = sharedPreferences.edit(); editor.putInt(autoResumeTrackCurrentRetryKey, retryAttempts); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } public void setRecordingTrack(long id) { Editor editor = sharedPreferences.edit(); editor.putLong(recordingTrackKey, id); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } public void setSelectedTrack(long id) { Editor editor = sharedPreferences.edit(); editor.putLong(selectedTrackKey, id); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } public void shutdown() { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java index ee1e021cc..8b81a44df 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java @@ -36,14 +36,12 @@ import com.google.android.apps.mytracks.services.tasks.SplitTask; import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory; import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatisticsBuilder; -import com.google.android.apps.mytracks.util.ApiFeatures; -import com.google.android.apps.mytracks.util.ApiLevelAdapter; import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.maps.mytracks.R; +import com.google.common.annotations.VisibleForTesting; import android.app.Notification; -import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.ContentValues; @@ -80,7 +78,6 @@ public class TrackRecordingService extends Service { static final int MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS = 3; - private NotificationManager notificationManager; private LocationManager locationManager; private WakeLock wakeLock; @@ -243,8 +240,6 @@ public class TrackRecordingService extends Service { super.onCreate(); Log.d(TAG, "TrackRecordingService.onCreate"); providerUtils = MyTracksProviderUtils.Factory.get(this); - notificationManager = - (NotificationManager) getSystemService(NOTIFICATION_SERVICE); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); setUpTaskExecutors(); @@ -369,7 +364,6 @@ public class TrackRecordingService extends Service { // Make sure we have no indirect references to this service. locationManager = null; - notificationManager = null; providerUtils = null; binder.detachFromService(); binder = null; @@ -485,8 +479,6 @@ public class TrackRecordingService extends Service { * Shows the notification message and icon in the notification bar. */ private void showNotification() { - final ApiLevelAdapter apiLevelAdapter = - ApiFeatures.getInstance().getApiAdapter(); if (isRecording) { Notification notification = new Notification( R.drawable.arrow_320, null /* tickerText */, @@ -497,16 +489,24 @@ public class TrackRecordingService extends Service { notification.setLatestEventInfo(this, getString(R.string.my_tracks_app_name), getString(R.string.track_record_notification), contentIntent); notification.flags += Notification.FLAG_NO_CLEAR; - apiLevelAdapter.startForeground(this, notificationManager, 1, - notification); + startForegroundService(notification); } else { - apiLevelAdapter.stopForeground(this, notificationManager, 1); + stopForegroundService(); } } + @VisibleForTesting + protected void startForegroundService(Notification notification) { + startForeground(1, notification); + } + + @VisibleForTesting + protected void stopForegroundService() { + stopForeground(true); + } + private void setUpTaskExecutors() { - announcementExecutor = new PeriodicTaskExecutor( - this, new StatusAnnouncerFactory(ApiFeatures.getInstance())); + announcementExecutor = new PeriodicTaskExecutor(this, new StatusAnnouncerFactory()); splitExecutor = new PeriodicTaskExecutor(this, new SplitTask.Factory()); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java index 4a3bc512b..eb174091e 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java @@ -18,7 +18,7 @@ package com.google.android.apps.mytracks.services.sensors; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -31,9 +31,6 @@ import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.UUID; /** * This class does all the work for setting up and managing Bluetooth @@ -44,9 +41,6 @@ import java.util.UUID; * @author Sandor Dornbush */ public class BluetoothConnectionManager { - // Unique UUID for this application - private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - private MessageParser parser; // Member fields @@ -254,41 +248,13 @@ public class BluetoothConnectionManager { // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { - tmp = getSocket(); + tmp = ApiAdapterFactory.getApiAdapter().getBluetoothSocket(device); } catch (IOException e) { Log.e(Constants.TAG, "create() failed", e); } socket = tmp; } - private BluetoothSocket getSocket() throws IOException { - if (ApiFeatures.getInstance().hasBluetoothDeviceCreateInsecureRfcommSocketToServiceRecord()) { - try { - return device.createInsecureRfcommSocketToServiceRecord(SPP_UUID); - } catch (IOException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } - } else { - try { - Class c = device.getClass(); - Method insecure = c.getMethod("createInsecureRfcommSocket", Integer.class); - insecure.setAccessible(true); - return (BluetoothSocket) insecure.invoke(device, 1); - } catch (SecurityException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } catch (NoSuchMethodException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } catch (IllegalArgumentException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } catch (IllegalAccessException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } catch (InvocationTargetException e) { - Log.e(Constants.TAG, "Unable to get insecure connect.", e); - } - } - return device.createRfcommSocketToServiceRecord(SPP_UUID); - } - @Override public void run() { Log.d(Constants.TAG, "BEGIN mConnectThread"); diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java index b70e0fddf..a8354ee95 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.services.sensors; import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import java.util.Arrays; @@ -62,8 +62,7 @@ public class ZephyrMessageParser implements MessageParser { // 0x1A00316550003162 produces erroneous values for Cadence and needs // a workaround based on the stride counter. // Firmware values range from field 3 to 10 (inclusive) of the byte buffer. - byte[] hardwareFirmwareId = ApiFeatures.getInstance().getApiAdapter() - .copyByteArray(buffer, 3, 11); + byte[] hardwareFirmwareId = ApiAdapterFactory.getApiAdapter().copyByteArray(buffer, 3, 11); Sensor.SensorData.Builder cadence = Sensor.SensorData.newBuilder(); if (Arrays.equals(hardwareFirmwareId, CADENCE_BUG_FW_ID)) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java index 4c0db0864..e72635f79 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java @@ -22,7 +22,7 @@ import com.dsi.ant.AntMesg; import com.dsi.ant.exception.AntInterfaceException; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.maps.mytracks.R; import android.content.Context; @@ -135,7 +135,7 @@ public class AntDirectSensorManager extends AntSensorManager { Constants.SETTINGS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putInt(context.getString(R.string.ant_heart_rate_sensor_id_key), deviceNumberHRM); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } private void handleMessageResponse(byte[] rawMessage) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java index 1db754b4d..1006e4a6b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java @@ -22,7 +22,7 @@ import com.dsi.ant.AntMesg; import com.dsi.ant.exception.AntInterfaceException; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.apps.mytracks.util.SystemUtils; import com.google.android.maps.mytracks.R; @@ -199,7 +199,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager { Constants.SETTINGS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putInt(context.getString(R.string.ant_srm_bridge_sensor_id_key), deviceNumber); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } private void handleMessageResponse(byte[] rawMessage) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactory.java b/MyTracks/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactory.java index 739b81cb3..7e8b56b37 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactory.java @@ -15,10 +15,9 @@ */ package com.google.android.apps.mytracks.services.tasks; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; import android.content.Context; -import android.media.AudioManager; /** * Factory which wraps construction and setup of text-to-speech announcements in @@ -28,30 +27,11 @@ import android.media.AudioManager; */ public class StatusAnnouncerFactory implements PeriodicTaskFactory { - private final boolean hasTts; - - public StatusAnnouncerFactory(ApiFeatures apiFeatures) { - this.hasTts = apiFeatures.hasTextToSpeech(); + public StatusAnnouncerFactory() { } @Override public PeriodicTask create(Context context) { - if (hasTts) { - return ApiFeatures.getInstance().getApiAdapter().getStatusAnnouncerTask(context); - } else { - return null; - } - } - - /** - * Returns the appropriate volume stream for controlling announcement - * volume. - */ - public int getVolumeStream() { - if (hasTts) { - return StatusAnnouncerTask.getVolumeStream(); - } else { - return AudioManager.USE_DEFAULT_STREAM_TYPE; - } + return ApiAdapterFactory.getApiAdapter().getStatusAnnouncerTask(context); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/Api10Adapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/Api10Adapter.java new file mode 100644 index 000000000..6e9250531 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/util/Api10Adapter.java @@ -0,0 +1,43 @@ +/* + * 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.util; + +import com.google.android.apps.mytracks.Constants; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.util.Log; + +import java.io.IOException; + + +/** + * API level 10 specific implementation of the {@link ApiAdapter}. + * + * @author Jimmy Shih + */ +public class Api10Adapter extends Api9Adapter { + + @Override + public BluetoothSocket getBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException { + try { + return bluetoothDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { + Log.d(Constants.TAG, "Unable to create insecure connection", e); + } + return bluetoothDevice.createRfcommSocketToServiceRecord(SPP_UUID); + }; +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel3Adapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/Api7Adapter.java similarity index 63% rename from MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel3Adapter.java rename to MyTracks/src/com/google/android/apps/mytracks/util/Api7Adapter.java index dcd033e14..50f1320fd 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel3Adapter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/Api7Adapter.java @@ -15,50 +15,31 @@ */ package com.google.android.apps.mytracks.util; -import static com.google.android.apps.mytracks.Constants.TAG; - +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; import com.google.android.apps.mytracks.services.tasks.PeriodicTask; import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerTask; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.apache.ApacheHttpTransport; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; +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 java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** - * API level 3 specific implementation of the {@link ApiLevelAdapter}. + * API level 7 specific implementation of the {@link ApiAdapter}. * * @author Bartlomiej Niechwiej */ -public class ApiLevel3Adapter implements ApiLevelAdapter { +public class Api7Adapter implements ApiAdapter { - @Override - public void startForeground(Service service, - NotificationManager notificationManager, int id, - Notification notification) { - setServiceForeground(service, true); - - notificationManager.notify(id, notification); - } - - @Override - public void stopForeground(Service service, - NotificationManager notificationManager, int id) { - setServiceForeground(service, false); - if (id != -1) { - notificationManager.cancel(id); - } - } - @Override public PeriodicTask getStatusAnnouncerTask(Context context) { return new StatusAnnouncerTask(context); @@ -74,24 +55,6 @@ public class ApiLevel3Adapter implements ApiLevelAdapter { }; } - private void setServiceForeground(Service service, boolean foreground) { - // setForeground has been completely removed in API level 11, so we use reflection. - try { - Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class); - setForegroundMethod.invoke(service, foreground); - } catch (SecurityException e) { - Log.e(TAG, "Unable to set service foreground state", e); - } catch (NoSuchMethodException e) { - Log.e(TAG, "Unable to set service foreground state", e); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to set service foreground state", e); - } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to set service foreground state", e); - } catch (InvocationTargetException e) { - Log.e(TAG, "Unable to set service foreground state", e); - } - } - @Override public void applyPreferenceChanges(Editor editor) { editor.commit(); @@ -114,4 +77,25 @@ public class ApiLevel3Adapter implements ApiLevelAdapter { public HttpTransport getHttpTransport() { return new ApacheHttpTransport(); } + + @Override + public BluetoothSocket getBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException { + try { + Class 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(SPP_UUID); + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel8Adapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/Api8Adapter.java similarity index 50% rename from MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel8Adapter.java rename to MyTracks/src/com/google/android/apps/mytracks/util/Api8Adapter.java index 35696189d..f8371e081 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel8Adapter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/Api8Adapter.java @@ -1,3 +1,18 @@ +/* + * 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.util; import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; @@ -8,11 +23,11 @@ import com.google.android.apps.mytracks.services.tasks.PeriodicTask; import android.content.Context; /** - * API level 8 specific implementation of the {@link ApiLevelAdapter}. + * API level 8 specific implementation of the {@link ApiAdapter}. * * @author Jimmy Shih */ -public class ApiLevel8Adapter extends ApiLevel5Adapter { +public class Api8Adapter extends Api7Adapter { @Override public PeriodicTask getStatusAnnouncerTask(Context context) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel9Adapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/Api9Adapter.java similarity index 61% rename from MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel9Adapter.java rename to MyTracks/src/com/google/android/apps/mytracks/util/Api9Adapter.java index 5ab6ab0aa..86fb12d3d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel9Adapter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/Api9Adapter.java @@ -1,3 +1,18 @@ +/* + * 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.util; import com.google.android.apps.mytracks.Constants; @@ -11,11 +26,11 @@ import android.util.Log; import java.util.Arrays; /** - * API level 9 specific implementation of the {@link ApiLevelAdapter}. + * API level 9 specific implementation of the {@link ApiAdapter}. * * @author Rodrigo Damazio */ -public class ApiLevel9Adapter extends ApiLevel8Adapter { +public class Api9Adapter extends Api8Adapter { @Override public void applyPreferenceChanges(Editor editor) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapter.java new file mode 100644 index 000000000..0d4d2d286 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapter.java @@ -0,0 +1,105 @@ +/* + * 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.io.backup.BackupPreferencesListener; +import com.google.android.apps.mytracks.services.tasks.PeriodicTask; +import com.google.api.client.http.HttpTransport; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.content.SharedPreferences; + +import java.io.IOException; +import java.util.UUID; + +/** + * A set of methods that may be implemented differently depending on the Android + * API level. + * + * @author Bartlomiej Niechwiej + */ +public interface ApiAdapter { + + // Unique Bluetooth UUID for My Tracks + public static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + + /** + * Gets a status announcer task. + *

+ * Due to changes in API level 8. + * + * @param context the context + */ + public PeriodicTask getStatusAnnouncerTask(Context context); + + /** + * Gets a {@link BackupPreferencesListener}. + *

+ * 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 + * may not be applied immediately. + *

+ * Due to changes in API level 9. + * + * @param editor the editor + */ + public void applyPreferenceChanges(SharedPreferences.Editor editor); + + /** + * Enables strict mode where supported, only if this is a development build. + *

+ * Due to changes in API level 9. + */ + public void enableStrictMode(); + + /** + * Copies elements from an input byte array into a new byte array, from + * indexes start (inclusive) to end (exclusive). The end index must be less + * than or equal to the input length. + *

+ * Due to changes in API level 9. + * + * @param input the input byte array + * @param start the start index + * @param end the end index + * @return a new array containing elements from the input byte array. + */ + public byte[] copyByteArray(byte[] input, int start, int end); + + /** + * Gets a {@link HttpTransport}. + *

+ * Due to changes in API level 9. + */ + public HttpTransport getHttpTransport(); + + /** + * Gets a {@link BluetoothSocket}. + *

+ * Due to changes in API level 10. + * + * @param bluetoothDevice + */ + public BluetoothSocket getBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException; +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapterFactory.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapterFactory.java new file mode 100644 index 000000000..ef7eed0d2 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/util/ApiAdapterFactory.java @@ -0,0 +1,47 @@ +/* + * 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 android.os.Build; + +/** + * A factory to get the {@link ApiAdapter} for the current device. + * + * @author Rodrigo Damazio + */ +public class ApiAdapterFactory { + + private static ApiAdapter apiAdapter; + + /** + * Gets the {@link ApiAdapter} for the current device. + */ + public static ApiAdapter getApiAdapter() { + if (apiAdapter == null) { + int apiLevel = Integer.parseInt(Build.VERSION.SDK); + if (apiLevel >= 10) { + apiAdapter = new Api10Adapter(); + } else if (apiLevel >= 9) { + apiAdapter = new Api9Adapter(); + } else if (apiLevel >= 8) { + apiAdapter = new Api8Adapter(); + } else { + apiAdapter = new Api7Adapter(); + } + } + return apiAdapter; + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java deleted file mode 100644 index 700b5a2a6..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java +++ /dev/null @@ -1,122 +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 android.os.Build; -import android.util.Log; - -/** - * Utility class for determining if newer-API features are available on the - * current device. - * - * @author Rodrigo Damazio - */ -public class ApiFeatures { - - /** - * The API level of the Android version we are being run under. - */ - private static final int ANDROID_API_LEVEL = Integer.parseInt( - Build.VERSION.SDK); - - private static ApiFeatures instance; - - /** - * The API level adapter for the Android version we are being run under. - */ - private ApiLevelAdapter apiLevelAdapter; - - /** - * Returns the singleton instance of this class. - */ - public static ApiFeatures getInstance() { - if (instance == null) { - instance = new ApiFeatures(); - } - return instance; - } - - /** - * Injects a specific singleton instance, to be used for unit tests. - */ - @SuppressWarnings("hiding") - public static void injectInstance(ApiFeatures instance) { - ApiFeatures.instance = instance; - } - - /** - * Allow subclasses for mocking, but no direct instantiation. - */ - protected ApiFeatures() { - // It is safe to import unsupported classes as long as we only actually - // load the class when supported. - if (getApiLevel() >= 9) { - apiLevelAdapter = new ApiLevel9Adapter(); - } else if (getApiLevel() >= 8) { - apiLevelAdapter = new ApiLevel8Adapter(); - } else if (getApiLevel() >= 5) { - apiLevelAdapter = new ApiLevel5Adapter(); - } else { - apiLevelAdapter = new ApiLevel3Adapter(); - } - - Log.i(Constants.TAG, "Using API level adapter " + apiLevelAdapter.getClass()); - } - - public ApiLevelAdapter getApiAdapter() { - return apiLevelAdapter; - } - - // API Level 4 Changes - - /** - * Returns whether text-to-speech is available. - */ - public boolean hasTextToSpeech() { - return getApiLevel() >= 4; - } - - // API Level 5 Changes - - /** - * There's a bug (#1587) in Cupcake and Donut which prevents you from - * using a SQLiteQueryBuilder twice. That is, if you call buildQuery - * on a given instance (to log the statement for debugging), and then - * call query on the same instance to make it actually do the query, - * it'll regenerate the query for the second call, and will screw it - * up. Specifically, it'll add extra parens which don't belong. - */ - public boolean canReuseSQLiteQueryBuilder() { - return getApiLevel() >= 5; - } - - // API Level 10 changes - - /** - * Returns true if BluetoothDevice.createInsecureRfcommSocketToServiceRecord - * is available. - */ - public boolean hasBluetoothDeviceCreateInsecureRfcommSocketToServiceRecord() { - return getApiLevel() >= 10; - } - - // Visible for testing. - protected int getApiLevel() { - return ANDROID_API_LEVEL; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevelAdapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevelAdapter.java deleted file mode 100644 index f2180dfc2..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevelAdapter.java +++ /dev/null @@ -1,113 +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.io.backup.BackupPreferencesListener; -import com.google.android.apps.mytracks.services.tasks.PeriodicTask; -import com.google.api.client.http.HttpTransport; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; -import android.content.Context; -import android.content.SharedPreferences; - -/** - * A set of methods that may be implemented differently depending on the Android API level. - * - * @author Bartlomiej Niechwiej - */ -public interface ApiLevelAdapter { - - /** - * Puts the specified service into foreground. - * - * Due to changes in API level 5. - * - * @param service the service to be put in foreground. - * @param notificationManager the notification manager used to post the given - * notification. - * @param id the ID of the notification, unique within the application. - * @param notification the notification to post. - */ - void startForeground(Service service, NotificationManager notificationManager, - int id, Notification notification); - - /** - * Puts the given service into background. - * - * Due to changes in API level 5. - * - * @param service the service to put into background. - * @param notificationManager the notification manager to user when removing - * notifications. - * @param id the ID of the notification to be remove, or -1 if the - * notification shouldn't be removed. - */ - void stopForeground(Service service, NotificationManager notificationManager, - int id); - - /** - * Gets a status announcer task. - * - * Due to changes in API level 8. - */ - PeriodicTask getStatusAnnouncerTask(Context context); - - /** - * Gets a {@link BackupPreferencesListener}. - * - * Due to changes in API level 8. - */ - BackupPreferencesListener getBackupPreferencesListener(Context context); - - /** - * Applies all changes done to the given preferences editor. - * Changes may or may not be applied immediately. - * - * Due to changes in API level 9. - */ - void applyPreferenceChanges(SharedPreferences.Editor editor); - - /** - * Enables strict mode where supported, only if this is a development build. - * - * Due to changes in API level 9. - */ - void enableStrictMode(); - - /** - * Copies elements from the input byte array into a new byte array, from - * indexes start (inclusive) to end (exclusive). The end index must be less - * than or equal to input.length. - * - * Due to changes in API level 9. - * - * @param input the input byte array - * @param start the start index - * @param end the end index - * @return a new array containing elements from the input byte array - */ - byte[] copyByteArray(byte[] input, int start, int end); - - - /** - * Gets a {@link HttpTransport}. - * - * Due to changes in API level 9. - */ - HttpTransport getHttpTransport(); -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java index 96e8bd878..3b43adb41 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java @@ -20,7 +20,6 @@ import com.google.android.apps.mytracks.Constants; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; -import android.os.Build; import android.util.Log; import java.util.List; @@ -157,17 +156,11 @@ public abstract class BluetoothDeviceUtils { */ public static BluetoothDeviceUtils getInstance() { if (instance == null) { - if (!isBluetoothMethodSupported()) { - Log.d(Constants.TAG, "Using dummy bluetooth utils"); + try { + instance = new RealImpl(); + } catch (IllegalStateException ise) { + Log.w(Constants.TAG, "Oops, I mean, using dummy bluetooth utils", ise); instance = new DummyImpl(); - } else { - Log.d(Constants.TAG, "Using real bluetooth utils"); - try { - instance = new RealImpl(); - } catch (IllegalStateException ise) { - Log.w(Constants.TAG, "Oops, I mean, using dummy bluetooth utils", ise); - instance = new DummyImpl(); - } } } return instance; @@ -190,11 +183,4 @@ public abstract class BluetoothDeviceUtils { * @return the device's descriptor, or null if not found */ public abstract BluetoothDevice findDeviceMatching(String targetDeviceAddress); - - /** - * @return whether the bluetooth method is supported on this device - */ - public static boolean isBluetoothMethodSupported() { - return Integer.parseInt(Build.VERSION.SDK) >= 5; - } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtil.java b/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtil.java index 0008b6e8e..6d2253844 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtil.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtil.java @@ -45,7 +45,7 @@ public class EulaUtil { EULA_PREFERENCE_FILE, Context.MODE_PRIVATE); Editor editor = preferences.edit(); editor.putBoolean(EULA_PREFERENCE_KEY, true); - ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } public static String getEulaMessage(Context context) { diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/TestRecordingService.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/TestRecordingService.java new file mode 100644 index 000000000..2eaa20aad --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/TestRecordingService.java @@ -0,0 +1,64 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +package com.google.android.apps.mytracks.services; + +import android.app.Notification; +import android.app.Service; +import android.test.ServiceTestCase; +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A {@link TrackRecordingService} that can be used with {@link ServiceTestCase}. + * {@link ServiceTestCase} throws a null pointer exception when the service + * calls {@link Service#startForeground(int, android.app.Notification)} and + * {@link Service#stopForeground(boolean)}. + *

+ * See http://code.google.com/p/android/issues/detail?id=12122 + *

+ * Wrap these two methods in wrappers and override them. + * + * @author Jimmy Shih + */ +public class TestRecordingService extends TrackRecordingService { + + private static final String TAG = TestRecordingService.class.getSimpleName(); + + @Override + protected void startForegroundService(Notification notification) { + try { + Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class); + setForegroundMethod.invoke(this, true); + } catch (SecurityException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } + } + + @Override + protected void stopForegroundService() { + try { + Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class); + setForegroundMethod.invoke(this, false); + } catch (SecurityException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } + } +} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java index 25fe512ef..df0b079a3 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java @@ -24,7 +24,6 @@ import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.stats.TripStatistics; -import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.maps.mytracks.R; import android.content.BroadcastReceiver; @@ -57,8 +56,7 @@ import java.util.List; * is called, which prevents from testing multiple scenarios in a single * test (see runFunctionTest for more details). */ -public class TrackRecordingServiceTest - extends ServiceTestCase { +public class TrackRecordingServiceTest extends ServiceTestCase { private Context context; private MyTracksProviderUtils providerUtils; @@ -74,7 +72,7 @@ public class TrackRecordingServiceTest private Intent serviceIntent; public TrackRecordingServiceTest() { - super(TrackRecordingService.class); + super(TestRecordingService.class); } /** @@ -96,19 +94,6 @@ public class TrackRecordingServiceTest } } - /** - * A mock class that forces API level < 5 to make sure we can workaround a bug - * in ServiceTestCase (throwing a NPE). - * See http://code.google.com/p/android/issues/detail?id=12122 for more - * details. - */ - private static class MockApiFeatures extends ApiFeatures { - @Override - protected int getApiLevel() { - return 4; - } - } - @Override protected IBinder bindService(Intent intent) { if (getService() != null) { @@ -138,8 +123,6 @@ public class TrackRecordingServiceTest protected void setUp() throws Exception { super.setUp(); - ApiFeatures.injectInstance(new MockApiFeatures()); - MockContentResolver mockContentResolver = new MockContentResolver(); RenamingDelegatingContext targetContext = new RenamingDelegatingContext( getContext(), getContext(), "test."); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactoryTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactoryTest.java index ea9a8d441..91d9b3eeb 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactoryTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/tasks/StatusAnnouncerFactoryTest.java @@ -15,13 +15,6 @@ */ package com.google.android.apps.mytracks.services.tasks; -import com.google.android.apps.mytracks.services.tasks.PeriodicTask; -import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory; -import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerTask; -import com.google.android.apps.mytracks.util.ApiFeatures; - -import android.media.AudioManager; -import android.speech.tts.TextToSpeech; import android.test.AndroidTestCase; /** @@ -31,62 +24,9 @@ import android.test.AndroidTestCase; * @author Rodrigo Damazio */ public class StatusAnnouncerFactoryTest extends AndroidTestCase { - /** - * Mock version of the {@link ApiFeatures} class. - */ - private class MockApiFeatures extends ApiFeatures { - private boolean hasTts; - - public void setHasTextToSpeech(boolean hasTts) { - this.hasTts = hasTts; - } - - @Override - public boolean hasTextToSpeech() { - return hasTts; - } - } - - private MockApiFeatures apiFeatures; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - apiFeatures = new MockApiFeatures(); - } - public void testCreate() { - apiFeatures.setHasTextToSpeech(true); - PeriodicTaskFactory factory = - new StatusAnnouncerFactory(apiFeatures); + PeriodicTaskFactory factory = new StatusAnnouncerFactory(); PeriodicTask task = factory.create(getContext()); assertTrue(task instanceof StatusAnnouncerTask); } - - public void testCreate_notAvailable() { - apiFeatures.setHasTextToSpeech(false); - PeriodicTaskFactory factory = - new StatusAnnouncerFactory(apiFeatures); - PeriodicTask task = factory.create(getContext()); - assertNull(task); - } - - public void testGetVolumeStream() { - apiFeatures.setHasTextToSpeech(true); - StatusAnnouncerFactory factory = - new StatusAnnouncerFactory(apiFeatures); - assertEquals( - TextToSpeech.Engine.DEFAULT_STREAM, - factory.getVolumeStream()); - } - - public void testGetVolumeStream_notAvailable() { - apiFeatures.setHasTextToSpeech(false); - StatusAnnouncerFactory factory = - new StatusAnnouncerFactory(apiFeatures); - assertEquals( - AudioManager.USE_DEFAULT_STREAM_TYPE, - factory.getVolumeStream()); - } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel5Adapter.java b/MyTracksTest/src/com/google/android/apps/mytracks/util/ApiAdapterFactoryTest.java similarity index 51% rename from MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel5Adapter.java rename to MyTracksTest/src/com/google/android/apps/mytracks/util/ApiAdapterFactoryTest.java index 0f963f70f..4b73a6a6f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiLevel5Adapter.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/util/ApiAdapterFactoryTest.java @@ -15,27 +15,15 @@ */ package com.google.android.apps.mytracks.util; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; +import junit.framework.TestCase; /** - * API level 5 specific implementation of the {@link ApiLevelAdapter}. + * Tests {@link ApiAdapterFactory}. * - * @author Bartlomiej Niechwiej + * @author Rodrigo Damazio */ -public class ApiLevel5Adapter extends ApiLevel3Adapter { - - @Override - public void startForeground(Service service, - NotificationManager notificationManager, int id, - Notification notification) { - service.startForeground(id, notification); - } - - @Override - public void stopForeground(Service service, - NotificationManager notificationManager, int id) { - service.stopForeground(id != -1); +public class ApiAdapterFactoryTest extends TestCase { + public void testGetApiLevelAdapter() { + assertNotNull(ApiAdapterFactory.getApiAdapter()); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/util/ApiFeaturesTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/util/ApiFeaturesTest.java deleted file mode 100644 index 5b08a975f..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/util/ApiFeaturesTest.java +++ /dev/null @@ -1,62 +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 junit.framework.TestCase; - -/** - * Tests the API feature detection code in {@link ApiFeatures}. - * This test requires Froyo+ to run. - * - * @author Rodrigo Damazio - */ -public class ApiFeaturesTest extends TestCase { - - private TestableApiFeatures features; - - private class TestableApiFeatures extends ApiFeatures { - private int apiLevel; - - public void setApiLevel(int apiLevel) { - this.apiLevel = apiLevel; - } - - @Override - protected int getApiLevel() { - return apiLevel; - } - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - - features = new TestableApiFeatures(); - } - - public void testHasTextToSpeech() { - features.setApiLevel(3); - assertFalse(features.hasTextToSpeech()); - for (int i = 4; i <= 8; i++) { - features.setApiLevel(i); - assertTrue(features.hasTextToSpeech()); - } - } - - public void testGetApiAdapter() { - assertNotNull(features.getApiAdapter()); - } -}