Merging from head.

This commit is contained in:
Rodrigo Damazio
2011-01-03 13:05:30 -02:00
22 changed files with 165 additions and 37 deletions
+1
View File
@@ -2,5 +2,6 @@ syntax:glob
*/bin */bin
*/gen/** */gen/**
*/proguard/**
.metadata .metadata
MyTracksTest/annotations.log MyTracksTest/annotations.log
+1
View File
@@ -172,6 +172,7 @@ limitations under the License.
<uses-sdk android:minSdkVersion="3"/> <uses-sdk android:minSdkVersion="3"/>
<supports-screens <supports-screens
android:xlargeScreens="true"
android:largeScreens="true" android:largeScreens="true"
android:normalScreens="true" android:normalScreens="true"
android:smallScreens="true" android:smallScreens="true"
+2 -1
View File
@@ -10,5 +10,6 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=Google Inc.:Google APIs:8 target=Google Inc.:Google APIs:9
proguard.config=proguard.cfg
android.library.reference.1=../MyTracksLib/ android.library.reference.1=../MyTracksLib/
+10
View File
@@ -1,3 +1,4 @@
-target 6
-optimizationpasses 5 -optimizationpasses 5
-dontusemixedcaseclassnames -dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclasses
@@ -5,9 +6,18 @@
-verbose -verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# Add the libraries, but ignore warnings about them
-libraryjars libs
-libraryjars ../MyTracksLib/libs
-dontwarn com.google.android.googleapps.**
-dontwarn com.android.common.**
-dontwarn com.google.android.gsf.**
# Keep everything android references from XMLs
-keep public class * extends android.app.Activity -keep public class * extends android.app.Activity
-keep public class * extends android.app.Application -keep public class * extends android.app.Application
-keep public class * extends android.app.Service -keep public class * extends android.app.Service
-keep public class * extends android.app,backup.BackupAgent
-keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider -keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -82,7 +83,8 @@ class CheckUnits {
} }
private static void recordCheckPerformed(SharedPreferences preferences) { private static void recordCheckPerformed(SharedPreferences preferences) {
preferences.edit().putBoolean(PREFERENCE_UNITS_CHECKED, true).commit(); ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
preferences.edit().putBoolean(PREFERENCE_UNITS_CHECKED, true));
} }
private CheckUnits() { private CheckUnits() {
@@ -15,6 +15,7 @@
*/ */
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.ResourceUtils; import com.google.android.apps.mytracks.util.ResourceUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -77,7 +78,8 @@ class Eula {
} }
private static void accept(Activity activity, SharedPreferences preferences) { private static void accept(Activity activity, SharedPreferences preferences) {
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true).commit(); ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
Intent startIntent = new Intent(activity, WelcomeActivity.class); Intent startIntent = new Intent(activity, WelcomeActivity.class);
activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME); activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME);
} }
@@ -41,6 +41,7 @@ import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.services.TrackRecordingService; import com.google.android.apps.mytracks.services.TrackRecordingService;
import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -251,6 +252,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Log.d(MyTracksConstants.TAG, "MyTracks.onCreate"); Log.d(MyTracksConstants.TAG, "MyTracks.onCreate");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
instance = this; instance = this;
ApiFeatures apiFeatures = ApiFeatures.getInstance();
if (!MyTracksUtils.isRelease(this)) {
apiFeatures.getApiPlatformAdapter().enableStrictMode();
}
providerUtils = MyTracksProviderUtils.Factory.get(this); providerUtils = MyTracksProviderUtils.Factory.get(this);
menuManager = new MenuManager(this); menuManager = new MenuManager(this);
sharedPreferences = getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); sharedPreferences = getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
@@ -258,7 +264,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// The volume we want to control is the Text-To-Speech volume // The volume we want to control is the Text-To-Speech volume
int volumeStream = int volumeStream =
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream(); new StatusAnnouncerFactory(apiFeatures).getVolumeStream();
setVolumeControlStream(volumeStream); setVolumeControlStream(volumeStream);
// We don't need a window title bar: // We don't need a window title bar:
@@ -1058,10 +1064,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* @param trackId the id of the track * @param trackId the id of the track
*/ */
public void setSelectedTrackId(final long trackId) { public void setSelectedTrackId(final long trackId) {
sharedPreferences ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
.edit() sharedPreferences
.putLong(getString(R.string.selected_track_key), trackId) .edit()
.commit(); .putLong(getString(R.string.selected_track_key), trackId));
} }
long getSelectedTrackId() { long getSelectedTrackId() {
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.AlertDialog; import android.app.AlertDialog;
@@ -63,7 +64,7 @@ public class MyTracksDeleteAllTracks extends Handler {
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putLong(context.getString(R.string.selected_track_key), -1); editor.putLong(context.getString(R.string.selected_track_key), -1);
editor.commit(); ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
if (done != null) { if (done != null) {
Handler h = new Handler(); Handler h = new Handler();
h.post(done); h.post(done);
@@ -62,24 +62,18 @@ public class ApiFeatures {
* Allow subclasses for mocking, but no direct instantiation. * Allow subclasses for mocking, but no direct instantiation.
*/ */
protected ApiFeatures() { protected ApiFeatures() {
if (getApiLevel() >= 5) { if (getApiLevel() >= 9) {
try { apiPlatformAdapter = new GingerbreadPlatformAdapter();
Class<?> clazz = Class.forName( } else if (getApiLevel() >= 5) {
"com.google.android.apps.mytracks.util.EclairPlatformAdapter"); apiPlatformAdapter = new EclairPlatformAdapter();
apiPlatformAdapter = (ApiPlatformAdapter) clazz.newInstance(); } else {
} catch (Exception e) {
Log.i(MyTracksConstants.TAG, "ApiFeatures: Unable to instantiate Eclair"
+ " platform adapter", e);
}
}
if (apiPlatformAdapter == null) {
Log.i(MyTracksConstants.TAG, Log.i(MyTracksConstants.TAG,
"ApiFeatures: Using default platform adapter"); "ApiFeatures: Using default platform adapter");
// Cupcake adapter is always supported, so it's safe to do static linkage. // Cupcake adapter is always supported, so it's safe to do static linkage.
apiPlatformAdapter = new CupcakePlatformAdapter(); apiPlatformAdapter = new CupcakePlatformAdapter();
} }
} }
public ApiPlatformAdapter getApiPlatformAdapter() { public ApiPlatformAdapter getApiPlatformAdapter() {
return apiPlatformAdapter; return apiPlatformAdapter;
} }
@@ -107,7 +101,11 @@ public class ApiFeatures {
return true; return true;
} }
public boolean hasStrictMode() {
return getApiLevel() >= 9;
}
// Visible for testing. // Visible for testing.
protected int getApiLevel() { protected int getApiLevel() {
return ANDROID_API_LEVEL; return ANDROID_API_LEVEL;
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.SharedPreferences;
import android.os.HandlerThread; import android.os.HandlerThread;
/** /**
@@ -57,4 +58,15 @@ public interface ApiPlatformAdapter {
* @return true whether the handler has been stopped or not. * @return true whether the handler has been stopped or not.
*/ */
boolean stopHandlerThread(HandlerThread handlerThread); boolean stopHandlerThread(HandlerThread handlerThread);
/**
* Applies all changes done to the given preferences editor.
* Changes may or may not be applied immediately.
*/
void applyPreferenceChanges(SharedPreferences.Editor editor);
/**
* Enables strict mode where supported, only if this is a development build.
*/
void enableStrictMode();
} }
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.SharedPreferences.Editor;
import android.os.HandlerThread; import android.os.HandlerThread;
/** /**
@@ -50,4 +51,14 @@ public class CupcakePlatformAdapter implements ApiPlatformAdapter {
// Do nothing, as Cupcake doesn't provide quit(). // Do nothing, as Cupcake doesn't provide quit().
return false; return false;
} }
@Override
public void applyPreferenceChanges(Editor editor) {
editor.commit();
}
@Override
public void enableStrictMode() {
// Not supported
}
} }
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.SharedPreferences.Editor;
import android.os.HandlerThread; import android.os.HandlerThread;
/** /**
@@ -45,4 +46,14 @@ public class EclairPlatformAdapter implements ApiPlatformAdapter {
public boolean stopHandlerThread(HandlerThread handlerThread) { public boolean stopHandlerThread(HandlerThread handlerThread) {
return handlerThread.quit(); return handlerThread.quit();
} }
@Override
public void applyPreferenceChanges(Editor editor) {
editor.commit();
}
@Override
public void enableStrictMode() {
// Not supported
}
} }
@@ -0,0 +1,36 @@
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksConstants;
import android.content.SharedPreferences.Editor;
import android.os.StrictMode;
import android.util.Log;
/**
* The Gingerbread (API level 9) specific implememntation of the
* {@link ApiPlatformAdapter}.
*
* @author Rodrigo Damazio
*/
public class GingerbreadPlatformAdapter extends EclairPlatformAdapter {
@Override
public void applyPreferenceChanges(Editor editor) {
// Apply asynchronously
editor.apply();
}
@Override
public void enableStrictMode() {
Log.d(MyTracksConstants.TAG, "Enabling strict mode");
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDeath()
.build());
}
}
@@ -21,7 +21,12 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.GeoPoint; import com.google.android.maps.GeoPoint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.location.Location; import android.location.Location;
import android.os.StrictMode;
import android.util.Log; import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
@@ -34,6 +39,7 @@ import java.util.Stack;
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksUtils { public class MyTracksUtils {
private static final int RELEASE_SIGNATURE_HASHCODE = -1855564782;
/** /**
* Computes the distance on the two sphere between the point c0 and the line * Computes the distance on the two sphere between the point c0 and the line
@@ -246,6 +252,25 @@ public class MyTracksUtils {
(int) (location.getLongitude() * 1E6)); (int) (location.getLongitude() * 1E6));
} }
/**
* Returns whether or not this is a release build.
*/
public static boolean isRelease(Context context) {
try {
Signature [] sigs = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
for (Signature sig : sigs) {
if (sig.hashCode() == RELEASE_SIGNATURE_HASHCODE) {
return true;
}
}
} catch (NameNotFoundException e) {
Log.e(MyTracksConstants.TAG, "Unable to get signatures", e);
}
return false;
}
/** /**
* This is a utility class w/ only static memebers. * This is a utility class w/ only static memebers.
*/ */
+1 -1
View File
@@ -8,5 +8,5 @@
# project structure. # project structure.
# Project target. # Project target.
target=android-8 target=android-9
android.library=true android.library=true
@@ -861,18 +861,22 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
String select = TracksColumns._ID + "=" + id; String select = TracksColumns._ID + "=" + id;
return findTrackBy(select); return findTrackBy(select);
} }
@Override @Override
public List<Track> getAllTracks() { public List<Track> getAllTracks() {
Cursor cursor = getTracksCursor(null); Cursor cursor = getTracksCursor(null);
if (cursor == null || !cursor.moveToFirst()) { ArrayList<Track> tracks = new ArrayList<Track>();
return new ArrayList<Track>(); if (cursor != null) {
} tracks.ensureCapacity(cursor.getCount());
List<Track> tracks = new ArrayList<Track>(cursor.getCount()); if (cursor.moveToFirst()) {
do { do {
tracks.add(createTrack(cursor)); tracks.add(createTrack(cursor));
} while(cursor.moveToNext()); } while(cursor.moveToNext());
}
cursor.close();
}
return tracks; return tracks;
} }
+1 -1
View File
@@ -10,4 +10,4 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=Google Inc.:Google APIs:8 target=Google Inc.:Google APIs:9
@@ -38,7 +38,7 @@ public class PreferenceBackupHelperTest extends TestCase {
*/ */
private class MockPreferenceEditor implements SharedPreferences.Editor { private class MockPreferenceEditor implements SharedPreferences.Editor {
private Map<String, Object> newPreferences = new HashMap<String, Object>(preferenceValues); private Map<String, Object> newPreferences = new HashMap<String, Object>(preferenceValues);
@Override @Override
public Editor clear() { public Editor clear() {
newPreferences.clear(); newPreferences.clear();
@@ -51,6 +51,11 @@ public class PreferenceBackupHelperTest extends TestCase {
return true; return true;
} }
@Override
public void apply() {
commit();
}
@Override @Override
public Editor putBoolean(String key, boolean value) { public Editor putBoolean(String key, boolean value) {
return put(key, value); return put(key, value);
@@ -502,7 +502,7 @@ public class TrackRecordingServiceTest
public void testDeleteAllTracks_trackInProgress() throws Exception { public void testDeleteAllTracks_trackInProgress() throws Exception {
createDummyTrack(123, -1, true); createDummyTrack(123, -1, true);
assertEquals(1, providerUtils.getAllTracks().size()); assertEquals(1, providerUtils.getAllTracks().size());
ITrackRecordingService service = bindAndGetService(createStartIntent()); ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording()); assertTrue(service.isRecording());
+2 -1
View File
@@ -54,7 +54,8 @@ limitations under the License.
<uses-feature android:name="android.hardware.telephony" android:required="true"/> <uses-feature android:name="android.hardware.telephony" android:required="true"/>
<uses-feature android:name="android.hardware.telephony.gsm" android:required="false"/> <uses-feature android:name="android.hardware.telephony.gsm" android:required="false"/>
<uses-sdk android:minSdkVersion="3" /> <uses-sdk android:minSdkVersion="3" />
<supports-screens android:largeScreens="true" <supports-screens android:xlargeScreens="true"
android:largeScreens="true"
android:normalScreens="true" android:normalScreens="true"
android:smallScreens="true" android:smallScreens="true"
android:anyDensity="true" /> android:anyDensity="true" />
+2 -1
View File
@@ -8,5 +8,6 @@
# project structure. # project structure.
# Project target. # Project target.
target=Google Inc.:Google APIs:8 target=Google Inc.:Google APIs:9
proguard.config=proguard.cfg
android.library.reference.1=../MyTracksLib/ android.library.reference.1=../MyTracksLib/
+1 -1
View File
@@ -8,4 +8,4 @@
# project structure. # project structure.
# Project target. # Project target.
target=Google Inc.:Google APIs:8 target=Google Inc.:Google APIs:9