Fix #40 - Add code style template and reformat code.

This commit is contained in:
Sean Barbeau
2014-02-09 22:26:24 -05:00
parent 83a03e1ba9
commit cb1f50e68b
32 changed files with 1492 additions and 1024 deletions

175
AndroidStyle.xml Normal file
View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<code_scheme name="AndroidStyle">
<option name="JAVA_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="8"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</value>
</option>
<option name="FIELD_NAME_PREFIX" value="m"/>
<option name="STATIC_FIELD_NAME_PREFIX" value="m"/>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="9999"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="9999"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="com.google" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="com" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="junit" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="net" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="android" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="RIGHT_MARGIN" value="100"/>
<option name="JD_P_AT_EMPTY_LINES" value="false"/>
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true"/>
<option name="JD_KEEP_EMPTY_PARAMETER" value="false"/>
<option name="JD_KEEP_EMPTY_EXCEPTION" value="false"/>
<option name="JD_KEEP_EMPTY_RETURN" value="false"/>
<option name="JD_PRESERVE_LINE_FEEDS" value="true"/>
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD" value="1"/>
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="THROWS_LIST_WRAP" value="1"/>
<option name="EXTENDS_KEYWORD_WRAP" value="1"/>
<option name="THROWS_KEYWORD_WRAP" value="1"/>
<option name="METHOD_CALL_CHAIN_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="ASSIGNMENT_WRAP" value="1"/>
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true"/>
<option name="WRAP_COMMENTS" value="true"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<ADDITIONAL_INDENT_OPTIONS fileType="css">
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="java">
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="8"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="js">
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="jsp">
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="sql">
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="xml">
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<ADDITIONAL_INDENT_OPTIONS fileType="yml">
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="8"/>
<option name="TAB_SIZE" value="4"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</ADDITIONAL_INDENT_OPTIONS>
<codeStyleSettings language="JavaScript">
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD" value="1"/>
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="THROWS_LIST_WRAP" value="1"/>
<option name="EXTENDS_KEYWORD_WRAP" value="1"/>
<option name="THROWS_KEYWORD_WRAP" value="1"/>
<option name="METHOD_CALL_CHAIN_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="ASSIGNMENT_WRAP" value="1"/>
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true"/>
<option name="WRAP_COMMENTS" value="true"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
</codeStyleSettings>
</code_scheme>

View File

@@ -52,7 +52,7 @@ task askForPasswords << {
// Must create String because System.readPassword() returns char[]
// (and assigning that below fails silently)
def storePw = new String(System.console().readPassword("\nKeystore password: "))
def keyPw = new String(System.console().readPassword("Key password: "))
def keyPw = new String(System.console().readPassword("Key password: "))
android.signingConfigs.release.storePassword = storePw
android.signingConfigs.release.keyPassword = keyPw

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
<!-- Copyright (C) 2008-2013 The Android Open Source Project,
Sean J. Barbeau
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,57 +16,57 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.gpstest"
android:versionCode="11"
android:versionName="2.0.2">
package="com.android.gpstest"
android:versionCode="11"
android:versionName="2.0.2">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android Maps API V2 -->
<permission
android:name="com.android.gpstest.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.android.gpstest.permission.MAPS_RECEIVE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<!-- The following permission is not required to use
Google Maps Android API v2, but is recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:name=".Application"
android:label="@string/app_name"
android:name="com.android.gpstest.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.android.gpstest.permission.MAPS_RECEIVE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<!-- The following permission is not required to use
Google Maps Android API v2, but is recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:name=".Application"
android:label="@string/app_name"
android:icon="@drawable/gpstest_icon">
<uses-library android:name="com.google.android.maps" />
<uses-library android:name="com.google.android.maps"/>
<activity android:name=".GpsTestActivity"
android:theme="@style/GpsSwitchTheme"
android:configChanges="keyboard|keyboardHidden|orientation">
<activity android:name=".GpsTestActivity"
android:theme="@style/GpsSwitchTheme"
android:configChanges="keyboard|keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".Preferences"
android:label="@string/pref_title"
android:theme="@style/Theme.Sherlock">
<activity
android:name=".Preferences"
android:label="@string/pref_title"
android:theme="@style/Theme.Sherlock">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyDQ74tuldesS1VnK84CgeSq0v6FVe5Od-M"/>
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyDQ74tuldesS1VnK84CgeSq0v6FVe5Od-M"/>
</application>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" />
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19"/>
</manifest>

View File

@@ -1,20 +1,22 @@
package com.actionbarsherlock.app;
import android.app.Activity;
import android.support.v4.app.Watson.OnCreateOptionsMenuListener;
import android.support.v4.app.Watson.OnOptionsItemSelectedListener;
import android.support.v4.app.Watson.OnPrepareOptionsMenuListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.google.android.gms.maps.SupportMapFragment;
import com.actionbarsherlock.internal.view.menu.MenuItemWrapper;
import com.actionbarsherlock.internal.view.menu.MenuWrapper;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.maps.SupportMapFragment;
import android.app.Activity;
import android.support.v4.app.Watson.OnCreateOptionsMenuListener;
import android.support.v4.app.Watson.OnOptionsItemSelectedListener;
import android.support.v4.app.Watson.OnPrepareOptionsMenuListener;
public class SherlockMapFragment extends SupportMapFragment implements
OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener,
OnOptionsItemSelectedListener {
private SherlockFragmentActivity mActivity;
public SherlockFragmentActivity getSherlockActivity() {

View File

@@ -21,33 +21,34 @@ import android.preference.PreferenceManager;
/**
* Holds application-wide state
*
*
* @author Sean J. Barbeau
*/
public class Application extends android.app.Application {
private SharedPreferences mPrefs;
private static Application mApp;
private SharedPreferences mPrefs;
@Override
public void onCreate() {
super.onCreate();
private static Application mApp;
mApp = this;
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
}
@Override
@Override
public void onCreate() {
super.onCreate();
mApp = this;
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
}
@Override
public void onTerminate() {
super.onTerminate();
mApp = null;
}
public static Application get() {
return mApp;
}
public static Application get() {
return mApp;
}
public static SharedPreferences getPrefs() {
return get().mPrefs;
}
public static SharedPreferences getPrefs() {
return get().mPrefs;
}
}

View File

@@ -17,6 +17,16 @@
package com.android.gpstest;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.LocationSource;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.maps.android.SphericalUtil;
import com.actionbarsherlock.app.SherlockMapFragment;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
@@ -31,58 +41,60 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.actionbarsherlock.app.SherlockMapFragment;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.LocationSource;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.maps.android.SphericalUtil;
public class GpsMapFragment extends SherlockMapFragment
implements GpsTestActivity.GpsTestListener, View.OnClickListener, LocationSource,
GoogleMap.OnCameraChangeListener, GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener,
GoogleMap.OnCameraChangeListener, GoogleMap.OnMapClickListener,
GoogleMap.OnMapLongClickListener,
GoogleMap.OnMyLocationButtonClickListener {
private final static String TAG = "GpsStatusActivity";
private GoogleMap mMap;
private LatLng mLatLng;
private OnLocationChangedListener mListener; //Used to update the map with new location
private OnLocationChangedListener mListener; //Used to update the map with new location
// Camera control
private long mLastMapTouchTime = 0;
private CameraPosition mlastCameraPosition;
// Constants used to control how the camera animates to a position
public static final float CAMERA_INITIAL_ZOOM = 18.0f;
public static final float CAMERA_INITIAL_ZOOM = 18.0f;
public static final float CAMERA_INITIAL_BEARING = 0.0f;
public static final float CAMERA_INITIAL_TILT = 45.0f;
public static final float CAMERA_ANCHOR_ZOOM = 19.0f;
public static final float CAMERA_MIN_TILT = 0.0f;
public static final float CAMERA_MAX_TILT = 90.0f;
public static final double TARGET_OFFSET_METERS = 150;
// Amount of time the user must not touch the map for the automatic camera movements to kick in
public static final long MOVE_MAP_INTERACTION_THRESHOLD = 5 * 1000; // milliseconds
private boolean mGotFix;
// User preferences for map rotation and tilt based on sensors
private boolean mRotate;
private boolean mTilt;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
mMap = getMap();
if (isGoogleMapsInstalled()) {
if (mMap != null) {
//Show the location on the map
if (mMap != null) {
//Show the location on the map
mMap.setMyLocationEnabled(true);
//Set location source
mMap.setLocationSource(this);
@@ -94,44 +106,52 @@ public class GpsMapFragment extends SherlockMapFragment
mMap.setOnMyLocationButtonClickListener(this);
GpsTestActivity.getInstance().addListener(this);
}
}
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(getString(R.string.please_install_google_maps));
builder.setCancelable(false);
builder.setPositiveButton(getString(R.string.install), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
startActivity(intent);
builder.setPositiveButton(getString(R.string.install),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("market://details?id=com.google.android.apps.maps"));
startActivity(intent);
getActivity().finish();
}
});
getActivity().finish();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
return v;
}
@Override
public void onResume() {
SharedPreferences settings = Application.getPrefs();
if (mMap != null && settings != null) {
if (mMap.getMapType() != Integer.valueOf(settings.getString(getString(R.string.pref_key_map_type), String.valueOf(GoogleMap.MAP_TYPE_NORMAL)))) {
mMap.setMapType(Integer.valueOf(settings.getString(getString(R.string.pref_key_map_type), String.valueOf(GoogleMap.MAP_TYPE_NORMAL))));
}
SharedPreferences settings = Application.getPrefs();
if (mMap != null && settings != null) {
if (mMap.getMapType() != Integer.valueOf(
settings.getString(getString(R.string.pref_key_map_type),
String.valueOf(GoogleMap.MAP_TYPE_NORMAL)))) {
mMap.setMapType(Integer.valueOf(
settings.getString(getString(R.string.pref_key_map_type),
String.valueOf(GoogleMap.MAP_TYPE_NORMAL))));
}
mRotate = settings.getBoolean(getString(R.string.pref_key_rotate_map_with_compass), true);
mRotate = settings
.getBoolean(getString(R.string.pref_key_rotate_map_with_compass), true);
mTilt = settings.getBoolean(getString(R.string.pref_key_tilt_map_with_sensors), true);
}
super.onResume();
}
super.onResume();
}
public void onClick(View v) {}
public void onClick(View v) {
}
public void gpsStart() {
public void gpsStart() {
mGotFix = false;
}
@@ -139,39 +159,43 @@ public class GpsMapFragment extends SherlockMapFragment
}
public void onLocationChanged(Location loc) {
//Update real-time location on map
if (mListener != null) {
mListener.onLocationChanged(loc);
}
//Update real-time location on map
if (mListener != null) {
mListener.onLocationChanged(loc);
}
mLatLng = new LatLng(loc.getLatitude(), loc.getLongitude());
if (mMap != null) {
//Get bounds for detection of real-time location within bounds
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
if (!mGotFix &&
(!bounds.contains(mLatLng) ||
mMap.getCameraPosition().zoom < (mMap.getMaxZoomLevel() / 2))) {
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(mLatLng)
.zoom(CAMERA_INITIAL_ZOOM)
.bearing(CAMERA_INITIAL_BEARING)
.tilt(CAMERA_INITIAL_TILT)
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
mGotFix = true;
}
if (mMap != null) {
//Get bounds for detection of real-time location within bounds
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
if (!mGotFix &&
(!bounds.contains(mLatLng) ||
mMap.getCameraPosition().zoom < (mMap.getMaxZoomLevel() / 2))) {
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(mLatLng)
.zoom(CAMERA_INITIAL_ZOOM)
.bearing(CAMERA_INITIAL_BEARING)
.tilt(CAMERA_INITIAL_TILT)
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
mGotFix = true;
}
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {}
public void onProviderDisabled(String provider) {
}
public void onGpsStatusChanged(int event, GpsStatus status) {}
public void onGpsStatusChanged(int event, GpsStatus status) {
}
@Override
public void onOrientationChanged(double orientation, double tilt) {
@@ -185,7 +209,8 @@ public class GpsMapFragment extends SherlockMapFragment
and the user hasn't touched the map lately, then do the map camera reposition
*/
if (mLatLng != null && mRotate
&& System.currentTimeMillis() - mLastMapTouchTime > MOVE_MAP_INTERACTION_THRESHOLD) {
&& System.currentTimeMillis() - mLastMapTouchTime
> MOVE_MAP_INTERACTION_THRESHOLD) {
if (!mTilt || Double.isNaN(tilt)) {
tilt = mlastCameraPosition != null ? mlastCameraPosition.tilt : 0;
@@ -199,7 +224,8 @@ public class GpsMapFragment extends SherlockMapFragment
tilt(clampedTilt).
bearing((float) orientation).
zoom((float) (CAMERA_ANCHOR_ZOOM + (tilt / CAMERA_MAX_TILT))).
target(mTilt ? SphericalUtil.computeOffset(mLatLng, offset, orientation) : mLatLng).
target(mTilt ? SphericalUtil.computeOffset(mLatLng, offset, orientation)
: mLatLng).
build();
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
@@ -209,12 +235,13 @@ public class GpsMapFragment extends SherlockMapFragment
* Clamps a value between the given positive min and max. If abs(value) is less than
* min, then min is returned. If abs(value) is greater than max, then max is returned.
* If abs(value) is between min and max, then abs(value) is returned.
* @param min minimum allowed value
*
* @param min minimum allowed value
* @param value value to be evaluated
* @param max maximum allowed value
* @param max maximum allowed value
* @return clamped value between the min and max
*/
private static double clamp (double min, double value, double max) {
private static double clamp(double min, double value, double max) {
value = Math.abs(value);
if (value >= min && value <= max) {
return value;
@@ -226,32 +253,32 @@ public class GpsMapFragment extends SherlockMapFragment
/**
* Maps V2 Location updates
*/
@Override
public void activate(OnLocationChangedListener listener) {
mListener = listener;
}
@Override
public void activate(OnLocationChangedListener listener) {
mListener = listener;
}
/**
* Maps V2 Location updates
*/
@Override
public void deactivate() {
mListener = null;
}
/**
* Returns true if Google Maps is installed, false if it is not
* @return
*/
@SuppressWarnings("unused")
public boolean isGoogleMapsInstalled() {
try {
ApplicationInfo info = getActivity().getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0 );
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
/**
* Maps V2 Location updates
*/
@Override
public void deactivate() {
mListener = null;
}
/**
* Returns true if Google Maps is installed, false if it is not
*/
@SuppressWarnings("unused")
public boolean isGoogleMapsInstalled() {
try {
ApplicationInfo info = getActivity().getPackageManager()
.getApplicationInfo("com.google.android.apps.maps", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
@Override
public void onCameraChange(CameraPosition cameraPosition) {

View File

@@ -17,6 +17,10 @@
package com.android.gpstest;
import com.actionbarsherlock.app.SherlockFragment;
import com.android.gpstest.util.GnssType;
import com.android.gpstest.util.GpsTestUtil;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
@@ -35,10 +39,6 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import com.actionbarsherlock.app.SherlockFragment;
import com.android.gpstest.util.GnssType;
import com.android.gpstest.util.GpsTestUtil;
import java.util.Iterator;
public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.GpsTestListener {
@@ -49,13 +49,14 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
// View dimensions, to draw the compass with the correct width and height
public static int mHeight;
public static int mWidth;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
mSkyView = new GpsSkyView(getActivity());
mSkyView = new GpsSkyView(getActivity());
GpsTestActivity.getInstance().addListener(this);
// Get the proper height and width of this view, to ensure the compass draws onscreen
@@ -80,16 +81,27 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
}
}
});
return mSkyView;
}
public void onLocationChanged(Location loc) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
public void gpsStart() {}
public void gpsStop() {}
public void onLocationChanged(Location loc) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
public void gpsStart() {
}
public void gpsStop() {
}
public void onGpsStatusChanged(int event, GpsStatus status) {
switch (event) {
@@ -119,23 +131,33 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
}
}
private static class GpsSkyView extends View implements GpsTestActivity.GpsTestListener {
private static class GpsSkyView extends View implements GpsTestActivity.GpsTestListener {
private Paint mHorizonActiveFillPaint, mHorizonInactiveFillPaint, mHorizonStrokePaint,
mGridStrokePaint,
mSatelliteFillPaint, mSatelliteStrokePaint, mNorthPaint, mNorthFillPaint, mPrnIdPaint;
mGridStrokePaint,
mSatelliteFillPaint, mSatelliteStrokePaint, mNorthPaint, mNorthFillPaint,
mPrnIdPaint;
Context mContext;
WindowManager mWindowManager;
private double mOrientation = 0.0;
private boolean mStarted;
private float mSnrs[], mElevs[], mAzims[];
private int mPrns[];
private int mSvCount;
private final float mSnrThresholds[];
private final int mSnrColors[];
private static final int SAT_RADIUS = 10;
private static final float PRN_TEXT_SCALE = 2.5f;
public GpsSkyView(Context context) {
@@ -176,8 +198,8 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
mSatelliteStrokePaint.setStrokeWidth(2.0f);
mSatelliteStrokePaint.setAntiAlias(true);
mSnrThresholds = new float[] { 0.0f, 10.0f, 20.0f, 30.0f };
mSnrColors = new int[] { Color.GRAY, Color.RED, Color.YELLOW, Color.GREEN };
mSnrThresholds = new float[]{0.0f, 10.0f, 20.0f, 30.0f};
mSnrColors = new int[]{Color.GRAY, Color.RED, Color.YELLOW, Color.GREEN};
mNorthPaint = new Paint();
mNorthPaint.setColor(Color.BLACK);
@@ -240,8 +262,8 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
private void drawLine(Canvas c, float x1, float y1, float x2, float y2) {
// rotate the line based on orientation
double angle = Math.toRadians(-mOrientation);
float cos = (float)Math.cos(angle);
float sin = (float)Math.sin(angle);
float cos = (float) Math.cos(angle);
float sin = (float) Math.sin(angle);
float centerX = (x1 + x2) / 2.0f;
float centerY = (y1 + y2) / 2.0f;
@@ -261,12 +283,13 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
private void drawHorizon(Canvas c, int s) {
float radius = s / 2;
c.drawCircle(radius, radius, radius, mStarted ? mHorizonActiveFillPaint : mHorizonInactiveFillPaint);
c.drawCircle(radius, radius, radius,
mStarted ? mHorizonActiveFillPaint : mHorizonInactiveFillPaint);
drawLine(c, 0, radius, 2 * radius, radius);
drawLine(c, radius, 0, radius, 2 * radius);
c.drawCircle(radius, radius, elevationToRadius(s, 60.0f), mGridStrokePaint);
c.drawCircle(radius, radius, elevationToRadius(s, 30.0f), mGridStrokePaint);
c.drawCircle(radius, radius, elevationToRadius(s, 0.0f), mGridStrokePaint);
c.drawCircle(radius, radius, elevationToRadius(s, 0.0f), mGridStrokePaint);
c.drawCircle(radius, radius, radius, mHorizonStrokePaint);
}
@@ -291,14 +314,14 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(x1, y1);
path.lineTo(x2,y2);
path.lineTo(x3,y3);
path.lineTo(x1,y1);
path.lineTo(x2, y2);
path.lineTo(x3, y3);
path.lineTo(x1, y1);
path.close();
// Rotate arrow around center point
Matrix matrix = new Matrix();
matrix.postRotate((float)-mOrientation, radius, radius);
matrix.postRotate((float) -mOrientation, radius, radius);
path.transform(matrix);
c.drawPath(path, mNorthPaint);
@@ -317,10 +340,10 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
radius = elevationToRadius(s, elev);
azim -= mOrientation;
angle = (float)Math.toRadians(azim);
angle = (float) Math.toRadians(azim);
x = (float)((s / 2) + (radius * Math.sin(angle)));
y = (float)((s / 2) - (radius * Math.cos(angle)));
x = (float) ((s / 2) + (radius * Math.sin(angle)));
y = (float) ((s / 2) - (radius * Math.cos(angle)));
// Change shape based on satellite operator
GnssType operator = GpsTestUtil.getGnssType(prn);
@@ -330,12 +353,15 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
c.drawCircle(x, y, SAT_RADIUS, mSatelliteStrokePaint);
break;
case GLONASS:
c.drawRect(x-SAT_RADIUS, y+SAT_RADIUS, x+SAT_RADIUS, y-SAT_RADIUS, thisPaint);
c.drawRect(x-SAT_RADIUS, y+SAT_RADIUS, x+SAT_RADIUS, y-SAT_RADIUS, mSatelliteStrokePaint);
c.drawRect(x - SAT_RADIUS, y + SAT_RADIUS, x + SAT_RADIUS, y - SAT_RADIUS,
thisPaint);
c.drawRect(x - SAT_RADIUS, y + SAT_RADIUS, x + SAT_RADIUS, y - SAT_RADIUS,
mSatelliteStrokePaint);
break;
}
c.drawText(String.valueOf(prn), x - (int) (SAT_RADIUS * PRN_X_SCALE), y + (int) (SAT_RADIUS * PRN_Y_SCALE), mPrnIdPaint);
c.drawText(String.valueOf(prn), x - (int) (SAT_RADIUS * PRN_X_SCALE),
y + (int) (SAT_RADIUS * PRN_Y_SCALE), mPrnIdPaint);
}
private float elevationToRadius(int s, float elev) {
@@ -379,9 +405,9 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
f = (snr - threshold) / (nextThreshold - threshold);
r3 = (int)(r2 * f + r1 * (1.0f - f));
g3 = (int)(g2 * f + g1 * (1.0f - f));
b3 = (int)(b2 * f + b1 * (1.0f - f));
r3 = (int) (r2 * f + r1 * (1.0f - f));
g3 = (int) (g2 * f + g1 * (1.0f - f));
b3 = (int) (b2 * f + b1 * (1.0f - f));
c3 = Color.rgb(r3, g3, b3);
newPaint.setColor(c3);
@@ -399,7 +425,8 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
protected void onDraw(Canvas canvas) {
int minScreenDimen;
minScreenDimen = (GpsSkyFragment.mWidth < GpsSkyFragment.mHeight) ? GpsSkyFragment.mWidth : GpsSkyFragment.mHeight;
minScreenDimen = (GpsSkyFragment.mWidth < GpsSkyFragment.mHeight)
? GpsSkyFragment.mWidth : GpsSkyFragment.mHeight;
drawHorizon(canvas, minScreenDimen);
@@ -409,8 +436,10 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
int numSats = mSvCount;
for (int i = 0; i < numSats; i++) {
if (mSnrs[i] > 0.0f && (mElevs[i] != 0.0f || mAzims[i] != 0.0f))
drawSatellite(canvas, minScreenDimen, mElevs[i], mAzims[i], mSnrs[i], mPrns[i]);
if (mSnrs[i] > 0.0f && (mElevs[i] != 0.0f || mAzims[i] != 0.0f)) {
drawSatellite(canvas, minScreenDimen, mElevs[i], mAzims[i], mSnrs[i],
mPrns[i]);
}
}
}
}
@@ -422,18 +451,31 @@ public class GpsSkyFragment extends SherlockFragment implements GpsTestActivity.
}
@Override
public void gpsStart() {}
public void gpsStart() {
}
@Override
public void gpsStop() {}
public void gpsStop() {
}
@Override
public void onGpsStatusChanged(int event, GpsStatus status) {}
public void onGpsStatusChanged(int event, GpsStatus status) {
}
@Override
public void onLocationChanged(Location location) {}
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {}
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {}
public void onProviderDisabled(String provider) {
}
}
}

View File

@@ -17,6 +17,10 @@
package com.android.gpstest;
import com.actionbarsherlock.app.SherlockFragment;
import com.android.gpstest.util.GnssType;
import com.android.gpstest.util.GpsTestUtil;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
@@ -35,36 +39,44 @@ import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment;
import com.android.gpstest.util.GnssType;
import com.android.gpstest.util.GpsTestUtil;
import java.util.Iterator;
public class GpsStatusFragment extends SherlockFragment implements GpsTestActivity.GpsTestListener {
private final static String TAG = "GpsStatusActivity";
private Resources mRes;
private TextView mLatitudeView, mLongitudeView, mFixTimeView, mTTFFView, mAltitudeView,
mAccuracyView, mSpeedView, mBearingView;
private SvGridAdapter mAdapter;
private int mSvCount, mPrns[];
private float mSnrs[], mSvElevations[], mSvAzimuths[];
private int mEphemerisMask, mAlmanacMask, mUsedInFixMask;
private long mFixTime;
private boolean mNavigating, mGotFix;
private Drawable flagUsa, flagRussia;
private static final int PRN_COLUMN = 0;
private static final int FLAG_IMAGE_COLUMN = 1;
private static final int SNR_COLUMN = 2;
private static final int ELEVATION_COLUMN = 3;
private static final int AZIMUTH_COLUMN = 4;
private static final int FLAGS_COLUMN = 5;
private static final int COLUMN_COUNT = 6;
private static final String EMPTY_LAT_LONG = " ";
@@ -82,11 +94,11 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
return result;
}
public void onLocationChanged(Location location) {
if (!mGotFix) {
mTTFFView.setText(GpsTestActivity.getInstance().mTtff);
mGotFix = true;
}
public void onLocationChanged(Location location) {
if (!mGotFix) {
mTTFFView.setText(GpsTestActivity.getInstance().mTtff);
mGotFix = true;
}
mLatitudeView.setText(doubleToString(location.getLatitude(), 7) + " ");
mLongitudeView.setText(doubleToString(location.getLongitude(), 7) + " ");
mFixTime = location.getTime();
@@ -113,13 +125,17 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
updateFixTime();
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {}
public void onProviderDisabled(String provider) {
}
private class SvGridAdapter extends BaseAdapter {
public SvGridAdapter(Context c) {
mContext = c;
}
@@ -214,35 +230,35 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
text = new String(flags);
break;
}
}
}
if (textView == null) {
textView = new TextView(mContext);
}
if (textView == null) {
textView = new TextView(mContext);
}
textView.setText(text);
return textView;
textView.setText(text);
return textView;
}
private Context mContext;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRes = getResources();
View v = inflater.inflate(R.layout.gps_status, container,
false);
mLatitudeView = (TextView)v.findViewById(R.id.latitude);
mLongitudeView = (TextView)v.findViewById(R.id.longitude);
mFixTimeView = (TextView)v.findViewById(R.id.fix_time);
mTTFFView = (TextView)v.findViewById(R.id.ttff);
mAltitudeView = (TextView)v.findViewById(R.id.altitude);
mAccuracyView = (TextView)v.findViewById(R.id.accuracy);
mSpeedView = (TextView)v.findViewById(R.id.speed);
mBearingView = (TextView)v.findViewById(R.id.bearing);
false);
mLatitudeView = (TextView) v.findViewById(R.id.latitude);
mLongitudeView = (TextView) v.findViewById(R.id.longitude);
mFixTimeView = (TextView) v.findViewById(R.id.fix_time);
mTTFFView = (TextView) v.findViewById(R.id.ttff);
mAltitudeView = (TextView) v.findViewById(R.id.altitude);
mAccuracyView = (TextView) v.findViewById(R.id.accuracy);
mSpeedView = (TextView) v.findViewById(R.id.speed);
mBearingView = (TextView) v.findViewById(R.id.bearing);
mLatitudeView.setText(EMPTY_LAT_LONG);
mLongitudeView.setText(EMPTY_LAT_LONG);
@@ -250,14 +266,14 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
flagUsa = getResources().getDrawable(R.drawable.ic_flag_usa);
flagRussia = getResources().getDrawable(R.drawable.ic_flag_russia);
GridView gridView = (GridView)v.findViewById(R.id.sv_grid);
GridView gridView = (GridView) v.findViewById(R.id.sv_grid);
mAdapter = new SvGridAdapter(getActivity());
gridView.setAdapter(mAdapter);
gridView.setFocusable(false);
gridView.setFocusableInTouchMode(false);
GpsTestActivity.getInstance().addListener(this);
return v;
}
@@ -284,10 +300,10 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
private void updateFixTime() {
if (mFixTime == 0 || !GpsTestActivity.getInstance().mStarted) {
mFixTimeView.setText("");
mFixTimeView.setText("");
} else {
mFixTimeView.setText(DateUtils.getRelativeTimeSpanString(
mFixTime, System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));
mFixTime, System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));
}
}
@@ -308,8 +324,8 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
@SuppressLint("NewApi")
public void gpsStart() {
//Reset flag for detecting first fix
mGotFix = false;
//Reset flag for detecting first fix
mGotFix = false;
}
public void gpsStop() {
@@ -325,7 +341,7 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
setStarted(false);
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
case GpsStatus.GPS_EVENT_FIRST_FIX:
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
@@ -335,7 +351,8 @@ public class GpsStatusFragment extends SherlockFragment implements GpsTestActivi
}
@Override
public void onOrientationChanged(double orientation, double tilt) {}
public void onOrientationChanged(double orientation, double tilt) {
}
private void updateStatus(GpsStatus status) {

View File

@@ -17,6 +17,15 @@
package com.android.gpstest;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.android.gpstest.util.GpsTestUtil;
import com.android.gpstest.view.ViewPagerMapBevelScroll;
import com.github.espiandev.showcaseview.ShowcaseView;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
@@ -50,66 +59,77 @@ import android.view.View;
import android.widget.CompoundButton;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.android.gpstest.util.GpsTestUtil;
import com.android.gpstest.view.ViewPagerMapBevelScroll;
import com.github.espiandev.showcaseview.ShowcaseView;
import java.util.ArrayList;
public class GpsTestActivity extends SherlockFragmentActivity
implements LocationListener, GpsStatus.Listener, ActionBar.TabListener, SensorEventListener {
implements LocationListener, GpsStatus.Listener, ActionBar.TabListener,
SensorEventListener {
private static final String TAG = "GpsTestActivity";
private LocationManager mService;
private LocationProvider mProvider;
private GpsStatus mStatus;
private ArrayList<GpsTestListener> mGpsTestListeners = new ArrayList<GpsTestListener>();
boolean mStarted;
private Location mLastLocation;
String mTtff;
private long minTime; // Min Time between location updates, in milliseconds
private static final int SECONDS_TO_MILLISECONDS = 1000;
private float minDistance; // Min Distance between location updates, in meters
private static GpsTestActivity sInstance;
org.jraf.android.backport.switchwidget.Switch mSwitch; //GPS on/off switch
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
* will keep every loaded fragment in memory. If this becomes too memory
* intensive, it may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPagerMapBevelScroll mViewPager;
ShowcaseView sv;
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
* will keep every loaded fragment in memory. If this becomes too memory
* intensive, it may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPagerMapBevelScroll mViewPager;
ShowcaseView sv;
ShowcaseView.ConfigOptions mOptions = new ShowcaseView.ConfigOptions();
private SensorManager mSensorManager;
// Holds sensor data
private static float[] mRotationMatrix = new float[16];
private static float[] mRemappedMatrix = new float[16];
private static float[] mValues = new float[3];
private static float[] mTruncatedRotationVector = new float[4];
private static boolean mTruncateVector = false;
static boolean mIsLargeScreen = false;
interface GpsTestListener extends LocationListener {
public void gpsStart();
public void gpsStop();
public void onGpsStatusChanged(int event, GpsStatus status);
public void onOrientationChanged(double orientation, double tilt);
}
@@ -125,19 +145,22 @@ public class GpsTestActivity extends SherlockFragmentActivity
if (!mStarted) {
mService.requestLocationUpdates(mProvider.getName(), minTime, minDistance, this);
mStarted = true;
// Show Toast only if the user has set minTime or minDistance to something other than default values
if (minTime != (long) (Double.valueOf(getString(R.string.pref_gps_min_time_default_sec)) * SECONDS_TO_MILLISECONDS) ||
minDistance != Float.valueOf(getString(R.string.pref_gps_min_distance_default_meters))) {
Toast.makeText(this, String.format(getString(R.string.gps_set_location_listener),
String.valueOf((double) minTime / SECONDS_TO_MILLISECONDS),String.valueOf(minDistance)), Toast.LENGTH_SHORT).show();
if (minTime != (long) (Double.valueOf(getString(R.string.pref_gps_min_time_default_sec))
* SECONDS_TO_MILLISECONDS) ||
minDistance != Float
.valueOf(getString(R.string.pref_gps_min_distance_default_meters))) {
Toast.makeText(this, String.format(getString(R.string.gps_set_location_listener),
String.valueOf((double) minTime / SECONDS_TO_MILLISECONDS),
String.valueOf(minDistance)), Toast.LENGTH_SHORT).show();
}
// Show the indeterminate progress bar on the action bar until first GPS status is shown
setSupportProgressBarIndeterminateVisibility(Boolean.TRUE);
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
setSupportProgressBarIndeterminateVisibility(Boolean.TRUE);
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
}
for (GpsTestListener listener : mGpsTestListeners) {
listener.gpsStart();
@@ -149,10 +172,10 @@ public class GpsTestActivity extends SherlockFragmentActivity
mService.removeUpdates(this);
mStarted = false;
// Stop progress bar
setSupportProgressBarIndeterminateVisibility(Boolean.FALSE);
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
setSupportProgressBarIndeterminateVisibility(Boolean.FALSE);
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
}
for (GpsTestListener listener : mGpsTestListeners) {
listener.gpsStop();
@@ -166,15 +189,15 @@ public class GpsTestActivity extends SherlockFragmentActivity
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(com.actionbarsherlock.R.style.Theme_Sherlock);
setTheme(com.actionbarsherlock.R.style.Theme_Sherlock);
super.onCreate(savedInstanceState);
sInstance = this;
// Set the default values from the XML file if this is the first
// execution of the app
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
mService = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
// Set the default values from the XML file if this is the first
// execution of the app
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
mService = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mProvider = mService.getProvider(LocationManager.GPS_PROVIDER);
if (mProvider == null) {
Log.e(TAG, "Unable to get GPS_PROVIDER");
@@ -185,11 +208,11 @@ public class GpsTestActivity extends SherlockFragmentActivity
}
mService.addGpsStatusListener(this);
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Request use of spinner for showing indeterminate progress, to show
// the user something is going on during long-running operations
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
// the user something is going on during long-running operations
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
// If we have a large screen, show all the fragments in one layout
if (GpsTestUtil.isLargeScreen(this)) {
@@ -198,23 +221,27 @@ public class GpsTestActivity extends SherlockFragmentActivity
} else {
setContentView(R.layout.activity_main);
}
initActionBar(savedInstanceState);
SharedPreferences settings = Application.getPrefs();
double tempMinTime = Double.valueOf(settings.getString(getString(R.string.pref_key_gps_min_time), getString(R.string.pref_gps_min_time_default_sec)));
minTime = (long) (tempMinTime * SECONDS_TO_MILLISECONDS);
minDistance = Float.valueOf(settings.getString(getString(R.string.pref_key_gps_min_distance), getString(R.string.pref_gps_min_distance_default_meters)));
if (settings.getBoolean(getString(R.string.pref_key_auto_start_gps), true)) {
gpsStart();
}
initActionBar(savedInstanceState);
SharedPreferences settings = Application.getPrefs();
double tempMinTime = Double.valueOf(
settings.getString(getString(R.string.pref_key_gps_min_time),
getString(R.string.pref_gps_min_time_default_sec)));
minTime = (long) (tempMinTime * SECONDS_TO_MILLISECONDS);
minDistance = Float.valueOf(
settings.getString(getString(R.string.pref_key_gps_min_distance),
getString(R.string.pref_gps_min_distance_default_meters)));
if (settings.getBoolean(getString(R.string.pref_key_auto_start_gps), true)) {
gpsStart();
}
}
@Override
protected void onResume() {
super.onResume();
super.onResume();
if (GpsTestUtil.isRotationVectorSensorSupported()) {
// Use the modern rotation vector sensors
@@ -236,13 +263,13 @@ public class GpsTestActivity extends SherlockFragmentActivity
/**
* Check preferences to see how they should be initialized
*/
SharedPreferences settings = Application.getPrefs();
checkKeepScreenOn(settings);
checkTimeAndDistance(settings);
checkTutorial(settings);
SharedPreferences settings = Application.getPrefs();
checkKeepScreenOn(settings);
checkTimeAndDistance(settings);
checkTutorial(settings);
}
@Override
@@ -257,74 +284,85 @@ public class GpsTestActivity extends SherlockFragmentActivity
private void promptEnableGps() {
new AlertDialog.Builder(this)
.setMessage(getString(R.string.enable_gps_message))
.setPositiveButton(getString(R.string.enable_gps_positive_button), new DialogInterface.OnClickListener() {
.setPositiveButton(getString(R.string.enable_gps_positive_button),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
})
.setNegativeButton(getString(R.string.enable_gps_negative_button), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
})
.setNegativeButton(getString(R.string.enable_gps_negative_button),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {}
})
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
private void checkTimeAndDistance(SharedPreferences settings) {
double tempMinTimeDouble = Double.valueOf(settings.getString(getString(R.string.pref_key_gps_min_time), "1"));
long minTimeLong = (long) (tempMinTimeDouble * SECONDS_TO_MILLISECONDS);
if (minTime != minTimeLong ||
minDistance != Float.valueOf(settings.getString(getString(R.string.pref_key_gps_min_distance), "0"))) {
// User changed preference values, get the new ones
minTime = minTimeLong;
minDistance = Float.valueOf(settings.getString(getString(R.string.pref_key_gps_min_distance), "0"));
// If the GPS is started, reset the location listener with the new values
if (mStarted) {
mService.requestLocationUpdates(mProvider.getName(), minTime, minDistance, this);
Toast.makeText(this, String.format(getString(R.string.gps_set_location_listener),
String.valueOf(tempMinTimeDouble),String.valueOf(minDistance)), Toast.LENGTH_SHORT).show();
}
}
}
private void checkTutorial(SharedPreferences settings) {
if (!settings.getBoolean(getString(R.string.pref_key_showed_v2_tutorial), false)) {
// If GPS is started, stop to clear the screen (we will start it again at the end of this method)
boolean lastStartState = mStarted;
if (mStarted) {
gpsStop();
}
// Show the user a tutorial on using the ActionBar button to start/stop GPS,
// either on first execution or when the user choose the option in the Preferences
mOptions.shotType = ShowcaseView.TYPE_ONE_SHOT;
mOptions.block = false;
mOptions.hideOnClickOutside = true;
mOptions.noButton = true;
sv = ShowcaseView.insertShowcaseViewWithType(ShowcaseView.ITEM_ACTION_ITEM, R.id.gps_switch, this,
R.string.showcase_gps_on_off_title, R.string.showcase_gps_on_off_message, mOptions);
sv.show();
SharedPreferences.Editor editor = Application.getPrefs().edit();
editor.putBoolean(getString(R.string.pref_key_showed_v2_tutorial), true);
editor.commit();
if (lastStartState) {
Handler h = new Handler();
// Restart the GPS, if it was previously started, with a slight delay to allow the UI to clear
// and allow the tutorial to be clearly visible
h.postDelayed(new Runnable() {
public void run() {
gpsStart();
}
}, 500);
}
}
double tempMinTimeDouble = Double
.valueOf(settings.getString(getString(R.string.pref_key_gps_min_time), "1"));
long minTimeLong = (long) (tempMinTimeDouble * SECONDS_TO_MILLISECONDS);
if (minTime != minTimeLong ||
minDistance != Float.valueOf(
settings.getString(getString(R.string.pref_key_gps_min_distance), "0"))) {
// User changed preference values, get the new ones
minTime = minTimeLong;
minDistance = Float.valueOf(
settings.getString(getString(R.string.pref_key_gps_min_distance), "0"));
// If the GPS is started, reset the location listener with the new values
if (mStarted) {
mService.requestLocationUpdates(mProvider.getName(), minTime, minDistance, this);
Toast.makeText(this, String.format(getString(R.string.gps_set_location_listener),
String.valueOf(tempMinTimeDouble), String.valueOf(minDistance)),
Toast.LENGTH_SHORT).show();
}
}
}
private void checkKeepScreenOn (SharedPreferences settings) {
private void checkTutorial(SharedPreferences settings) {
if (!settings.getBoolean(getString(R.string.pref_key_showed_v2_tutorial), false)) {
// If GPS is started, stop to clear the screen (we will start it again at the end of this method)
boolean lastStartState = mStarted;
if (mStarted) {
gpsStop();
}
// Show the user a tutorial on using the ActionBar button to start/stop GPS,
// either on first execution or when the user choose the option in the Preferences
mOptions.shotType = ShowcaseView.TYPE_ONE_SHOT;
mOptions.block = false;
mOptions.hideOnClickOutside = true;
mOptions.noButton = true;
sv = ShowcaseView
.insertShowcaseViewWithType(ShowcaseView.ITEM_ACTION_ITEM, R.id.gps_switch,
this,
R.string.showcase_gps_on_off_title,
R.string.showcase_gps_on_off_message, mOptions);
sv.show();
SharedPreferences.Editor editor = Application.getPrefs().edit();
editor.putBoolean(getString(R.string.pref_key_showed_v2_tutorial), true);
editor.commit();
if (lastStartState) {
Handler h = new Handler();
// Restart the GPS, if it was previously started, with a slight delay to allow the UI to clear
// and allow the tutorial to be clearly visible
h.postDelayed(new Runnable() {
public void run() {
gpsStart();
}
}, 500);
}
}
}
private void checkKeepScreenOn(SharedPreferences settings) {
if (mViewPager != null) {
if (settings.getBoolean(getString(R.string.pref_key_keep_screen_on), true)) {
mViewPager.setKeepScreenOn(true);
@@ -342,50 +380,50 @@ public class GpsTestActivity extends SherlockFragmentActivity
}
}
}
@Override
protected void onDestroy() {
mService.removeGpsStatusListener(this);
mService.removeUpdates(this);
super.onDestroy();
mService.removeGpsStatusListener(this);
mService.removeUpdates(this);
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
getSupportMenuInflater().inflate(R.menu.gps_menu, menu);
initGpsSwitch(menu);
getSupportMenuInflater().inflate(R.menu.gps_menu, menu);
initGpsSwitch(menu);
return true;
}
private void initGpsSwitch(com.actionbarsherlock.view.Menu menu) {
MenuItem item = menu.findItem(R.id.gps_switch);
if (item != null) {
mSwitch = (org.jraf.android.backport.switchwidget.Switch) item.getActionView();
if (mSwitch != null) {
// Initialize state of GPS switch before we set the listener, so we don't double-trigger start or stop
mSwitch.setChecked(mStarted);
// Set up listener for GPS on/off switch, since custom menu items on Action Bar don't play
// well with ABS and we can't handle in onOptionsItemSelected()
mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Turn GPS on or off
if (!isChecked && mStarted) {
gpsStop();
} else {
if (isChecked && !mStarted) {
gpsStart();
}
}
}
});
}
}
MenuItem item = menu.findItem(R.id.gps_switch);
if (item != null) {
mSwitch = (org.jraf.android.backport.switchwidget.Switch) item.getActionView();
if (mSwitch != null) {
// Initialize state of GPS switch before we set the listener, so we don't double-trigger start or stop
mSwitch.setChecked(mStarted);
// Set up listener for GPS on/off switch, since custom menu items on Action Bar don't play
// well with ABS and we can't handle in onOptionsItemSelected()
mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Turn GPS on or off
if (!isChecked && mStarted) {
gpsStop();
} else {
if (isChecked && !mStarted) {
gpsStart();
}
}
}
});
}
}
}
@Override
public boolean onPrepareOptionsMenu(com.actionbarsherlock.view.Menu menu) {
MenuItem item;
MenuItem item;
item = menu.findItem(R.id.send_location);
if (item != null) {
@@ -394,77 +432,77 @@ public class GpsTestActivity extends SherlockFragmentActivity
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean success;
// Handle menu item selection
switch (item.getItemId()) {
case R.id.gps_switch:
// Do nothing - this is handled by a separate listener added in onCreateOptionsMenu()
return true;
case R.id.delete_aiding_data:
// If GPS is currently running, stop it
boolean lastStartState = mStarted;
if (mStarted) {
gpsStop();
}
success = sendExtraCommand(getString(R.string.delete_aiding_data_command));
if (success) {
Toast.makeText(this,getString(R.string.delete_aiding_data_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,getString(R.string.delete_aiding_data_failure),
Toast.LENGTH_SHORT).show();
}
if (lastStartState) {
Handler h = new Handler();
// Restart the GPS, if it was previously started, with a slight delay,
// to refresh the assistance data
h.postDelayed(new Runnable() {
public void run() {
gpsStart();
}
}, 500);
}
return true;
case R.id.send_location:
sendLocation();
return true;
case R.id.force_time_injection:
success = sendExtraCommand(getString(R.string.force_time_injection_command));
if (success) {
Toast.makeText(this,getString(R.string.force_time_injection_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,getString(R.string.force_time_injection_failure),
Toast.LENGTH_SHORT).show();
}
return true;
case R.id.force_xtra_injection:
success = sendExtraCommand(getString(R.string.force_xtra_injection_command));
if (success) {
Toast.makeText(this,getString(R.string.force_xtra_injection_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,getString(R.string.force_xtra_injection_failure),
Toast.LENGTH_SHORT).show();
}
return true;
case R.id.menu_settings:
// Show settings menu
startActivity(new Intent(this, Preferences.class));
default:
return super.onOptionsItemSelected(item);
}
boolean success;
// Handle menu item selection
switch (item.getItemId()) {
case R.id.gps_switch:
// Do nothing - this is handled by a separate listener added in onCreateOptionsMenu()
return true;
case R.id.delete_aiding_data:
// If GPS is currently running, stop it
boolean lastStartState = mStarted;
if (mStarted) {
gpsStop();
}
success = sendExtraCommand(getString(R.string.delete_aiding_data_command));
if (success) {
Toast.makeText(this, getString(R.string.delete_aiding_data_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, getString(R.string.delete_aiding_data_failure),
Toast.LENGTH_SHORT).show();
}
if (lastStartState) {
Handler h = new Handler();
// Restart the GPS, if it was previously started, with a slight delay,
// to refresh the assistance data
h.postDelayed(new Runnable() {
public void run() {
gpsStart();
}
}, 500);
}
return true;
case R.id.send_location:
sendLocation();
return true;
case R.id.force_time_injection:
success = sendExtraCommand(getString(R.string.force_time_injection_command));
if (success) {
Toast.makeText(this, getString(R.string.force_time_injection_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, getString(R.string.force_time_injection_failure),
Toast.LENGTH_SHORT).show();
}
return true;
case R.id.force_xtra_injection:
success = sendExtraCommand(getString(R.string.force_xtra_injection_command));
if (success) {
Toast.makeText(this, getString(R.string.force_xtra_injection_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, getString(R.string.force_xtra_injection_failure),
Toast.LENGTH_SHORT).show();
}
return true;
case R.id.menu_settings:
// Show settings menu
startActivity(new Intent(this, Preferences.class));
default:
return super.onOptionsItemSelected(item);
}
}
public void onLocationChanged(Location location) {
mLastLocation = location;
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
// Reset the options menu to trigger updates to action bar menu items
invalidateOptionsMenu();
for (GpsTestListener listener : mGpsTestListeners) {
listener.onLocationChanged(location);
@@ -491,32 +529,32 @@ public class GpsTestActivity extends SherlockFragmentActivity
public void onGpsStatusChanged(int event) {
mStatus = mService.getGpsStatus(mStatus);
switch (event) {
case GpsStatus.GPS_EVENT_STARTED:
break;
case GpsStatus.GPS_EVENT_STOPPED:
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
int ttff = mStatus.getTimeToFirstFix();
if (ttff == 0) {
mTtff = "";
} else {
ttff = (ttff + 500) / 1000;
mTtff = Integer.toString(ttff) + " sec";
}
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
// Stop progress bar after the first status information is obtained
setSupportProgressBarIndeterminateVisibility(Boolean.FALSE);
break;
case GpsStatus.GPS_EVENT_STARTED:
break;
case GpsStatus.GPS_EVENT_STOPPED:
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
int ttff = mStatus.getTimeToFirstFix();
if (ttff == 0) {
mTtff = "";
} else {
ttff = (ttff + 500) / 1000;
mTtff = Integer.toString(ttff) + " sec";
}
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
// Stop progress bar after the first status information is obtained
setSupportProgressBarIndeterminateVisibility(Boolean.FALSE);
break;
}
// If the user is viewing the tutorial, we don't want to clutter the status screen, so return
if (sv != null && sv.isShown()) {
return;
return;
}
for (GpsTestListener listener : mGpsTestListeners) {
listener.onGpsStatusChanged(event, mStatus);
}
@@ -600,12 +638,13 @@ public class GpsTestActivity extends SherlockFragmentActivity
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void sendLocation() {
if (mLastLocation != null) {
Intent intent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("mailto", "", null));
Uri.fromParts("mailto", "", null));
String location = "http://maps.google.com/maps?geocode=&q=" +
Double.toString(mLastLocation.getLatitude()) + "," +
Double.toString(mLastLocation.getLongitude());
@@ -613,92 +652,96 @@ public class GpsTestActivity extends SherlockFragmentActivity
startActivity(intent);
}
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
if (mViewPager != null) {
mViewPager.setCurrentItem(tab.getPosition());
mViewPager.setCurrentItem(tab.getPosition());
}
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the primary sections of the app.
*/
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
public static final int NUMBER_OF_TABS = 3; // Used to set up TabListener
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the primary sections of the app.
*/
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
// Constants for the different fragments that will be displayed in tabs, in numeric order
public static final int GPS_STATUS_FRAGMENT = 0;
public static final int GPS_MAP_FRAGMENT = 1;
public static final int GPS_SKY_FRAGMENT = 2;
// Maintain handle to Fragments to avoid recreating them if one already
// exists
Fragment gpsStatus, gpsMap, gpsSky;
public static final int NUMBER_OF_TABS = 3; // Used to set up TabListener
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
// Constants for the different fragments that will be displayed in tabs, in numeric order
public static final int GPS_STATUS_FRAGMENT = 0;
@Override
public Fragment getItem(int i) {
switch (i) {
case GPS_STATUS_FRAGMENT:
if (gpsStatus == null) {
gpsStatus = new GpsStatusFragment();
}
return gpsStatus;
case GPS_MAP_FRAGMENT:
if (gpsMap == null) {
gpsMap = new GpsMapFragment();
}
return gpsMap;
case GPS_SKY_FRAGMENT:
if (gpsSky == null) {
gpsSky = new GpsSkyFragment();
}
return gpsSky;
}
return null; // This should never happen
}
public static final int GPS_MAP_FRAGMENT = 1;
@Override
public int getCount() {
return NUMBER_OF_TABS;
}
public static final int GPS_SKY_FRAGMENT = 2;
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case GPS_STATUS_FRAGMENT:
return getString(R.string.gps_status_tab);
case GPS_MAP_FRAGMENT:
return getString(R.string.gps_map_tab);
case GPS_SKY_FRAGMENT:
return getString(R.string.gps_sky_tab);
}
return null; // This should never happen
}
}
private void initActionBar(Bundle savedInstanceState) {
// Set up the action bar.
final com.actionbarsherlock.app.ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(com.actionbarsherlock.app.ActionBar.NAVIGATION_MODE_TABS);
actionBar.setTitle(getApplicationContext().getText(R.string.app_name));
// Maintain handle to Fragments to avoid recreating them if one already
// exists
Fragment gpsStatus, gpsMap, gpsSky;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
switch (i) {
case GPS_STATUS_FRAGMENT:
if (gpsStatus == null) {
gpsStatus = new GpsStatusFragment();
}
return gpsStatus;
case GPS_MAP_FRAGMENT:
if (gpsMap == null) {
gpsMap = new GpsMapFragment();
}
return gpsMap;
case GPS_SKY_FRAGMENT:
if (gpsSky == null) {
gpsSky = new GpsSkyFragment();
}
return gpsSky;
}
return null; // This should never happen
}
@Override
public int getCount() {
return NUMBER_OF_TABS;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case GPS_STATUS_FRAGMENT:
return getString(R.string.gps_status_tab);
case GPS_MAP_FRAGMENT:
return getString(R.string.gps_map_tab);
case GPS_SKY_FRAGMENT:
return getString(R.string.gps_sky_tab);
}
return null; // This should never happen
}
}
private void initActionBar(Bundle savedInstanceState) {
// Set up the action bar.
final com.actionbarsherlock.app.ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(com.actionbarsherlock.app.ActionBar.NAVIGATION_MODE_TABS);
actionBar.setTitle(getApplicationContext().getText(R.string.app_name));
// If we don't have a large screen, set up the tabs using the ViewPager
if (!mIsLargeScreen) {
if (!mIsLargeScreen) {
// page adapter contains all the fragment registrations
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
@@ -711,11 +754,11 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
// tab. We can also use ActionBar.Tab#select() to do this if we have a
// reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
@@ -727,5 +770,5 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
.setTabListener(this));
}
}
}
}
}

View File

@@ -16,6 +16,9 @@
package com.android.gpstest;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import com.android.gpstest.util.GpsTestUtil;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
@@ -28,44 +31,46 @@ import android.preference.PreferenceCategory;
import android.text.InputType;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import com.android.gpstest.util.GpsTestUtil;
public class Preferences extends SherlockPreferenceActivity {
Preference prefShowTutorial;
Preference prefAnalyzeGpsAccuracy;
EditTextPreference txtMinTime;
EditTextPreference txtMinDistance;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
prefShowTutorial = this.findPreference(getString(R.string.pref_key_showed_v2_tutorial));
prefShowTutorial.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference pref) {
// If the user taps on the tutorial preference, reset the flag to false
// and finish to go back to the GpsTestActivity
SharedPreferences.Editor editor = Application.getPrefs().edit();
editor.putBoolean(getString(R.string.pref_key_showed_v2_tutorial), false);
editor.commit();
finish();
return false;
}
});
prefAnalyzeGpsAccuracy = this.findPreference(getString(R.string.pref_key_analyze_gps_accuracy));
Preference prefShowTutorial;
Preference prefAnalyzeGpsAccuracy;
EditTextPreference txtMinTime;
EditTextPreference txtMinDistance;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
prefShowTutorial = this.findPreference(getString(R.string.pref_key_showed_v2_tutorial));
prefShowTutorial.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference pref) {
// If the user taps on the tutorial preference, reset the flag to false
// and finish to go back to the GpsTestActivity
SharedPreferences.Editor editor = Application.getPrefs().edit();
editor.putBoolean(getString(R.string.pref_key_showed_v2_tutorial), false);
editor.commit();
finish();
return false;
}
});
prefAnalyzeGpsAccuracy = this
.findPreference(getString(R.string.pref_key_analyze_gps_accuracy));
prefAnalyzeGpsAccuracy.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference pref) {
// Check to see if GPS Benchmark is already installed
Intent intent = getPackageManager().getLaunchIntentForPackage(getString(R.string.gps_benchmark_package_name));
Intent intent = getPackageManager()
.getLaunchIntentForPackage(getString(R.string.gps_benchmark_package_name));
if (intent != null) {
// Start GPS Benchmark
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -81,68 +86,74 @@ public class Preferences extends SherlockPreferenceActivity {
return false;
}
});
txtMinTime = (EditTextPreference) this.findPreference(getString(R.string.pref_key_gps_min_time));
txtMinTime.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_FLAG_DECIMAL);
// Verify minTime entry
txtMinTime.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (!verifyFloat(newValue)) {
// Tell user that entry must be valid decimal
Toast.makeText(
Preferences.this,
getString(R.string.pref_gps_min_time_invalid_entry),
Toast.LENGTH_SHORT).show();
return false;
} else {
return true;
}
}
});
txtMinDistance = (EditTextPreference) this.findPreference(getString(R.string.pref_key_gps_min_distance));
txtMinDistance.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_FLAG_DECIMAL);
// Verify minDistance entry
txtMinDistance.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (!verifyFloat(newValue)) {
// Tell user that entry must be valid decimal
Toast.makeText(
Preferences.this,
getString(R.string.pref_gps_min_distance_invalid_entry),
Toast.LENGTH_SHORT).show();
return false;
} else {
return true;
}
}
});
txtMinTime = (EditTextPreference) this
.findPreference(getString(R.string.pref_key_gps_min_time));
txtMinTime.getEditText()
.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
// Verify minTime entry
txtMinTime.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (!verifyFloat(newValue)) {
// Tell user that entry must be valid decimal
Toast.makeText(
Preferences.this,
getString(R.string.pref_gps_min_time_invalid_entry),
Toast.LENGTH_SHORT).show();
return false;
} else {
return true;
}
}
});
txtMinDistance = (EditTextPreference) this
.findPreference(getString(R.string.pref_key_gps_min_distance));
txtMinDistance.getEditText()
.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
// Verify minDistance entry
txtMinDistance.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (!verifyFloat(newValue)) {
// Tell user that entry must be valid decimal
Toast.makeText(
Preferences.this,
getString(R.string.pref_gps_min_distance_invalid_entry),
Toast.LENGTH_SHORT).show();
return false;
} else {
return true;
}
}
});
// Remove preferences that shouldn't be shown based on this device
if (!GpsTestUtil.isRotationVectorSensorSupported()) {
// We don't have tilt info, so remove this preference
CheckBoxPreference mCheckBoxTiltMap = (CheckBoxPreference) findPreference(getString(R.string.pref_key_tilt_map_with_sensors));
PreferenceCategory mMapCategory = (PreferenceCategory) findPreference(getString(R.string.pref_key_map_category));
CheckBoxPreference mCheckBoxTiltMap = (CheckBoxPreference) findPreference(
getString(R.string.pref_key_tilt_map_with_sensors));
PreferenceCategory mMapCategory = (PreferenceCategory) findPreference(
getString(R.string.pref_key_map_category));
mMapCategory.removePreference(mCheckBoxTiltMap);
}
}
/**
* Verify that the value is a valid float
*
* @param newValue entered value
* @return true if its a valid float, false if its not
*/
private boolean verifyFloat(Object newValue) {
try {
Float.parseFloat(newValue.toString());
return true;
} catch (Exception e) {
return false;
}
}
}
/**
* Verify that the value is a valid float
*
* @param newValue entered value
* @return true if its a valid float, false if its not
*/
private boolean verifyFloat(Object newValue) {
try {
Float.parseFloat(newValue.toString());
return true;
} catch (Exception e) {
return false;
}
}
}

View File

@@ -24,6 +24,7 @@ public class GpsTestUtil {
/**
* Returns the Global Navigation Satellite System (GNSS) for a satellite given the PRN
*
* @param prn PRN value provided by the GpsSatellite.getPrn() method
* @return GnssType for the given PRN
*/
@@ -38,8 +39,11 @@ public class GpsTestUtil {
}
/**
* Returns true if this device supports the Sensor.TYPE_ROTATION_VECTOR sensor, false if it doesn't
* @return true if this device supports the Sensor.TYPE_ROTATION_VECTOR sensor, false if it doesn't
* Returns true if this device supports the Sensor.TYPE_ROTATION_VECTOR sensor, false if it
* doesn't
*
* @return true if this device supports the Sensor.TYPE_ROTATION_VECTOR sensor, false if it
* doesn't
*/
public static boolean isRotationVectorSensorSupported() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
@@ -47,10 +51,11 @@ public class GpsTestUtil {
/**
* Returns true if the app is running on a large screen device, false if it is not
* @param context
*
* @return true if the app is running on a large screen device, false if it is not
*/
public static boolean isLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
}

View File

@@ -30,52 +30,53 @@ import android.view.View;
* next fragment via "bezel swipe" (i.e., swiping from the edge)
*/
public class ViewPagerMapBevelScroll extends ViewPager {
private static final int DEFAULT_SWIPE_MARGIN_WIDTH_DIP = 20;
private int swipeMarginWidth;
public ViewPagerMapBevelScroll(Context context) {
super(context);
setDefaultSwipeMargin(context);
}
public ViewPagerMapBevelScroll(Context context, AttributeSet attrs) {
super(context, attrs);
setDefaultSwipeMargin(context);
}
private void setDefaultSwipeMargin(final Context context) {
swipeMarginWidth = (int) (DEFAULT_SWIPE_MARGIN_WIDTH_DIP * context
.getResources().getDisplayMetrics().density);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ViewPagerMapBevelScroll) {
switch (getCurrentItem()) {
case SectionsPagerAdapter.GPS_STATUS_FRAGMENT:
break;
case SectionsPagerAdapter.GPS_MAP_FRAGMENT:
//If we should allow the map swipe, then return false
return !isAllowedMapSwipe(x, dx);
case SectionsPagerAdapter.GPS_SKY_FRAGMENT:
break;
}
}
return super.canScroll(v, checkV, dx, x, y);
}
/**
* Determines if the pointer movement event at x and moved pixels is
* considered an allowed swipe movement overriding the inner horizontal
* scroll content protection.
*
* @param x X coordinate of the active touch point
* @param dx Delta scrolled in pixels
* @return true if the movement should start a page swipe
*/
protected boolean isAllowedMapSwipe(final float x, final float dx) {
return ((x < swipeMarginWidth) && (dx > 0))
|| ((x > (getWidth() - swipeMarginWidth)) && (dx < 0));
}
private static final int DEFAULT_SWIPE_MARGIN_WIDTH_DIP = 20;
private int swipeMarginWidth;
public ViewPagerMapBevelScroll(Context context) {
super(context);
setDefaultSwipeMargin(context);
}
public ViewPagerMapBevelScroll(Context context, AttributeSet attrs) {
super(context, attrs);
setDefaultSwipeMargin(context);
}
private void setDefaultSwipeMargin(final Context context) {
swipeMarginWidth = (int) (DEFAULT_SWIPE_MARGIN_WIDTH_DIP * context
.getResources().getDisplayMetrics().density);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ViewPagerMapBevelScroll) {
switch (getCurrentItem()) {
case SectionsPagerAdapter.GPS_STATUS_FRAGMENT:
break;
case SectionsPagerAdapter.GPS_MAP_FRAGMENT:
//If we should allow the map swipe, then return false
return !isAllowedMapSwipe(x, dx);
case SectionsPagerAdapter.GPS_SKY_FRAGMENT:
break;
}
}
return super.canScroll(v, checkV, dx, x, y);
}
/**
* Determines if the pointer movement event at x and moved pixels is
* considered an allowed swipe movement overriding the inner horizontal
* scroll content protection.
*
* @param x X coordinate of the active touch point
* @param dx Delta scrolled in pixels
* @return true if the movement should start a page swipe
*/
protected boolean isAllowedMapSwipe(final float x, final float dx) {
return ((x < swipeMarginWidth) && (dx > 0))
|| ((x > (getWidth() - swipeMarginWidth)) && (dx < 0));
}
}

View File

@@ -16,10 +16,10 @@
*/
-->
<com.android.gpstest.view.ViewPagerMapBevelScroll
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GpsTestActivity" />
<com.android.gpstest.view.ViewPagerMapBevelScroll
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GpsTestActivity"/>

View File

@@ -17,23 +17,23 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/large_screen_layout">
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/large_screen_layout">
<fragment class="com.android.gpstest.GpsStatusFragment"
android:id="@+id/gps_status_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:id="@+id/gps_status_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment class="com.android.gpstest.GpsMapFragment"
android:id="@+id/gps_map_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:id="@+id/gps_map_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment class="com.android.gpstest.GpsSkyFragment"
android:id="@+id/gps_sky_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:id="@+id/gps_sky_fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>

View File

@@ -17,14 +17,14 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:id="@+id/fragment_map"
android:name=".GpsMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="tag_fragment_map" />
android:id="@+id/fragment_map"
android:name=".GpsMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="tag_fragment_map"/>
</LinearLayout>

View File

@@ -17,112 +17,112 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableLayout android:id="@+id/lat_long_table"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TableRow>
<TextView android:id="@+id/latitude_label"
android:text="@string/gps_latitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_latitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/latitude"
style="@style/info_value" />
style="@style/info_value"/>
<TextView android:id="@+id/fix_time_label"
android:text="@string/gps_fix_time_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_fix_time_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/fix_time"
style="@style/info_value" />
style="@style/info_value"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/longitude_label"
android:text="@string/gps_longitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_longitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/longitude"
style="@style/info_value" />
style="@style/info_value"/>
<TextView android:id="@+id/gps_ttff_label"
android:text="@string/gps_ttff_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_ttff_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/ttff"
style="@style/info_value" />
style="@style/info_value"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/altitude_label"
android:text="@string/gps_altitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_altitude_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/altitude"
style="@style/info_value" />
style="@style/info_value"/>
<TextView android:id="@+id/accuracy_label"
android:text="@string/gps_accuracy_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_accuracy_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/accuracy"
style="@style/info_value" />
style="@style/info_value"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/speed_label"
android:text="@string/gps_speed_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_speed_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/speed"
style="@style/info_value" />
style="@style/info_value"/>
<TextView android:id="@+id/bearing_label"
android:text="@string/gps_bearing_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label" />
android:text="@string/gps_bearing_label"
android:layout_gravity="right"
android:layout_marginRight="8dip"
style="@style/info_label"/>
<TextView android:id="@+id/bearing"
style="@style/info_value" />
style="@style/info_value"/>
</TableRow>
</TableLayout>
</LinearLayout>
<GridView android:id="@+id/sv_grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:verticalSpacing="1dp"
android:horizontalSpacing="2dp"
android:numColumns="6"
android:rowHeight="16dp"
android:columnWidth="50dp"
android:stretchMode="columnWidth"
android:listSelector="@android:color/transparent"
android:gravity="center"
/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:verticalSpacing="1dp"
android:horizontalSpacing="2dp"
android:numColumns="6"
android:rowHeight="16dp"
android:columnWidth="50dp"
android:stretchMode="columnWidth"
android:listSelector="@android:color/transparent"
android:gravity="center"
/>
</LinearLayout>

View File

@@ -16,8 +16,8 @@
*/
-->
<org.jraf.android.backport.switchwidget.Switch
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".GpsTestActivity" />
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".GpsTestActivity"/>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<com.github.espiandev.showcaseview.ShowcaseView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.github.espiandev.showcaseview.ShowcaseView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
</com.github.espiandev.showcaseview.ShowcaseView>

View File

@@ -17,31 +17,31 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/send_location"
android:title="@string/send_location"
android:icon="@drawable/social_share"
android:showAsAction="ifRoom|withText" />
android:title="@string/send_location"
android:icon="@drawable/social_share"
android:showAsAction="ifRoom|withText"/>
<!-- <item android:id="@+id/gps_start"
android:title="@string/gps_start"
android:icon="@drawable/av_play"
android:showAsAction="ifRoom|withText"
android:actionLayout="@layout/gps_switch" /> -->
<item android:id="@+id/gps_switch"
android:showAsAction="ifRoom|withText"
android:actionLayout="@layout/gps_switch" />
android:showAsAction="ifRoom|withText"
android:actionLayout="@layout/gps_switch"/>
<item android:id="@+id/force_time_injection"
android:title="@string/force_time_injection" />
android:title="@string/force_time_injection"/>
<item android:id="@+id/force_xtra_injection"
android:title="@string/force_xtra_injection" />
android:title="@string/force_xtra_injection"/>
<item android:id="@+id/delete_aiding_data"
android:title="@string/delete_aiding_data" />
android:title="@string/delete_aiding_data"/>
<item android:id="@+id/menu_settings"
android:title="@string/menu_settings"
android:orderInCategory="100"
android:showAsAction="never" />
android:title="@string/menu_settings"
android:orderInCategory="100"
android:showAsAction="never"/>
</menu>

View File

@@ -18,20 +18,20 @@
*/
-->
<resources>
<!-- Let the user choose between map views -->
<string-array name="map_type_entries">
<item>Map View</item>
<item>Hybrid View</item>
<item>Satellite View</item>
<item>Terrain View</item>
</string-array>
<!-- Let the user choose between map views -->
<string-array name="map_type_entries">
<item>Map View</item>
<item>Hybrid View</item>
<item>Satellite View</item>
<item>Terrain View</item>
</string-array>
<!-- These contants above and below match those in GoogleMap object:
https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/GoogleMap -->
<string-array name="map_type_values">
<item>1</item>
<item>4</item>
<item>2</item>
<item>3</item>
</string-array>
<!-- These contants above and below match those in GoogleMap object:
https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/GoogleMap -->
<string-array name="map_type_values">
<item>1</item>
<item>4</item>
<item>2</item>
<item>3</item>
</string-array>
</resources>

View File

@@ -19,21 +19,21 @@
-->
<resources>
<!-- Strings in this file should NOT be translated -->
<!-- Preference keys -->
<string name="pref_key_map_category">map_category</string>
<string name="pref_key_map_type">map_type</string>
<string name="pref_key_tilt_map_with_sensors">tilt_map</string>
<string name="pref_key_rotate_map_with_compass">rotate_map</string>
<string name="pref_key_gps_category">gps_category</string>
<string name="pref_key_auto_start_gps">auto_start_gps</string>
<string name="pref_key_gps_min_time">gps_min_time</string>
<string name="pref_key_gps_min_distance">gps_min_distance</string>
<string name="pref_key_display_category">display_category</string>
<string name="pref_key_keep_screen_on">keep_screen_on</string>
<string name="pref_key_about_category">about_category</string>
<string name="pref_key_showed_v2_tutorial">showed_v2_tutorial</string>
<string name="pref_key_analyze_gps_accuracy">analyze_gps_accuracy</string>
@@ -48,5 +48,7 @@
<string name="force_xtra_injection_command">force_xtra_injection</string>
<string name="gps_benchmark_package_name">com.gpsbenchmark.android</string>
<string name="gps_benchmark_url">http://play.google.com/store/apps/details?id=com.gpsbenchmark.android</string>
<string name="gps_benchmark_url">
http://play.google.com/store/apps/details?id=com.gpsbenchmark.android
</string>
</resources>

View File

@@ -29,29 +29,32 @@
<string name="menu_settings">Settings</string>
<string name="delete_aiding_data">Clear Aiding Data</string>
<string name="delete_aiding_data_success">Successfully deleted aiding data.</string>
<string name="delete_aiding_data_failure">Platform does not support deleting aiding data.</string>
<string name="delete_aiding_data_failure">Platform does not support deleting aiding data.
</string>
<string name="send_location">Send Location</string>
<string name="set_fix_frequency">Set Fix Frequency</string>
<string name="force_time_injection">Inject Time</string>
<string name="force_time_injection_success">Successfully injected time data.</string>
<string name="force_time_injection_failure">Platform does not support injecting time data.</string>
<string name="force_time_injection_failure">Platform does not support injecting time data.
</string>
<string name="force_xtra_injection">Inject XTRA Data</string>
<string name="force_xtra_injection_success">Successfully injected XTRA data.</string>
<string name="force_xtra_injection_failure">Platform does not support injecting XTRA data.</string>
<string name="force_xtra_injection_failure">Platform does not support injecting XTRA data.
</string>
<string name="zoom_in">Zoom In</string>
<string name="zoom_in">Zoom In</string>
<string name="zoom_out">Zoom Out</string>
<string name="mode_map">Map</string>
<string name="mode_satellite">Satellite</string>
<string name="gps_latitude_label">Lat: </string>
<string name="gps_longitude_label">Long: </string>
<string name="gps_fix_time_label">Time: </string>
<string name="gps_ttff_label">TTFF: </string>
<string name="gps_altitude_label">Alt: </string>
<string name="gps_accuracy_label">Acc: </string>
<string name="gps_speed_label">Speed: </string>
<string name="gps_bearing_label">Bearing: </string>
<string name="gps_latitude_label">Lat:</string>
<string name="gps_longitude_label">Long:</string>
<string name="gps_fix_time_label">Time:</string>
<string name="gps_ttff_label">TTFF:</string>
<string name="gps_altitude_label">Alt:</string>
<string name="gps_accuracy_label">Acc:</string>
<string name="gps_speed_label">Speed:</string>
<string name="gps_bearing_label">Bearing:</string>
<string name="gps_prn_column_label">PRN</string>
<string name="gps_flag_image_label">GNSS</string>
@@ -59,18 +62,22 @@
<string name="gps_elevation_column_label">Elev</string>
<string name="gps_azimuth_column_label">Azim</string>
<string name="gps_flags_column_label">Flags</string>
<string name="gps_not_supported">GPS not supported. Exiting app...</string>
<string name="gps_not_supported">GPS not supported. Exiting app...</string>
<string name="install">Install</string>
<string name="please_install_google_maps">Please install Google Maps</string>
<string name="enable_gps_message">GPS is disabled. Enable it now?</string>
<string name="enable_gps_positive_button">Enable GPS</string>
<string name="enable_gps_negative_button">No</string>
<string name="gps_set_location_listener">Started GPS with interval = %1$ss, min. dist. = %2$sm</string>
<string name="gps_set_location_listener">Started GPS with interval = %1$ss, min. dist. = %2$sm
</string>
<!-- User tutorial -->
<string name="showcase_gps_on_off_title">New controls!</string>
<string name="showcase_gps_on_off_message">&#8226; The On/Off switch starts/stops GPS\n&#8226; The \"Share\" button sends a location (shown after getting a GPS fix)\n\n<i>(tap to dismiss)</i></string>
<string name="showcase_gps_on_off_message">&#8226; The On/Off switch starts/stops GPS\n&#8226;
The \"Share\" button sends a location (shown after getting a GPS fix)\n\n
<i>(tap to dismiss)</i>
</string>
<!-- Preferences -->
<string name="pref_title">Settings</string>
<string name="pref_map_category_title">Map</string>
@@ -79,33 +86,38 @@
<string name="pref_map_type_dialog_title">Choose Map Type</string>
<string name="pref_rotate_map_with_compass_title">Rotate Map with Compass</string>
<string name="pref_rotate_map_with_compass_summary">Change the map orientation based on your direction</string>
<string name="pref_rotate_map_with_compass_summary">Change the map orientation based on your
direction
</string>
<string name="pref_tilt_map_with_sensors_title">First-person View</string>
<string name="pref_tilt_map_with_sensors_summary">Change to a first-person view when you hold up the device</string>
<string name="pref_tilt_map_with_sensors_summary">Change to a first-person view when you hold up
the device
</string>
<string name="pref_gps_category_title">GPS</string>
<string name="pref_auto_start_gps_title">Auto-Start GPS</string>
<string name="pref_auto_start_gps_summary">Start GPS when the app starts</string>
<string name="pref_gps_min_time_title">Interval</string>
<string name="pref_gps_min_time_summary">Time between GPS fixes, in seconds</string>
<string name="pref_gps_min_time_dialog_title">Enter an interval, in seconds</string>
<string name="pref_gps_min_time_invalid_entry">Interval must be a number</string>
<string name="pref_gps_min_distance_title">Min. Distance</string>
<string name="pref_gps_min_distance_summary">Minimum distance between GPS fixes, in meters</string>
<string name="pref_gps_min_distance_summary">Minimum distance between GPS fixes, in meters
</string>
<string name="pref_gps_min_distance_dialog_title">Enter a min. distance, in meters</string>
<string name="pref_gps_min_distance_invalid_entry">Min. Distance must be a number</string>
<string name="pref_analyze_gps_accuracy_title">Analyze GPS Accuracy</string>
<string name="pref_analyze_gps_accuracy_summary">Use GPS Benchmark to measure GPS error</string>
<string name="pref_display_category_title">Display</string>
<string name="pref_keep_screen_on_title">Keep Screen On</string>
<string name="pref_keep_screen_on_summary">Prevents the screen from turning off</string>
<string name="pref_about_category_title">About</string>
<string name="pref_about_category_title">About</string>
<string name="pref_show_tutorial_title">Show tutorial</string>
<string name="pref_show_tutorial_summary">Shows instructions for using the app</string>
</resources>

View File

@@ -1,72 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/pref_map_category_title"
android:key="@string/pref_key_map_category">
android:title="@string/pref_map_category_title"
android:key="@string/pref_key_map_category">
<ListPreference
android:key="@string/pref_key_map_type"
android:title="@string/pref_map_type_title"
android:summary="@string/pref_map_type_summary"
android:dialogTitle="@string/pref_map_type_dialog_title"
android:entries="@array/map_type_entries"
android:entryValues="@array/map_type_values"
android:defaultValue="1" />
android:key="@string/pref_key_map_type"
android:title="@string/pref_map_type_title"
android:summary="@string/pref_map_type_summary"
android:dialogTitle="@string/pref_map_type_dialog_title"
android:entries="@array/map_type_entries"
android:entryValues="@array/map_type_values"
android:defaultValue="1"/>
<CheckBoxPreference
android:key="@string/pref_key_rotate_map_with_compass"
android:title="@string/pref_rotate_map_with_compass_title"
android:summary="@string/pref_rotate_map_with_compass_summary"
android:defaultValue="true" />
android:key="@string/pref_key_rotate_map_with_compass"
android:title="@string/pref_rotate_map_with_compass_title"
android:summary="@string/pref_rotate_map_with_compass_summary"
android:defaultValue="true"/>
<CheckBoxPreference
android:key="@string/pref_key_tilt_map_with_sensors"
android:title="@string/pref_tilt_map_with_sensors_title"
android:summary="@string/pref_tilt_map_with_sensors_summary"
android:dependency="@string/pref_key_rotate_map_with_compass"
android:defaultValue="true" />
android:key="@string/pref_key_tilt_map_with_sensors"
android:title="@string/pref_tilt_map_with_sensors_title"
android:summary="@string/pref_tilt_map_with_sensors_summary"
android:dependency="@string/pref_key_rotate_map_with_compass"
android:defaultValue="true"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_gps_category_title"
android:key="@string/pref_key_gps_category">
android:title="@string/pref_gps_category_title"
android:key="@string/pref_key_gps_category">
<CheckBoxPreference
android:key="@string/pref_key_auto_start_gps"
android:title="@string/pref_auto_start_gps_title"
android:summary="@string/pref_auto_start_gps_summary"
android:defaultValue="true" />
android:key="@string/pref_key_auto_start_gps"
android:title="@string/pref_auto_start_gps_title"
android:summary="@string/pref_auto_start_gps_summary"
android:defaultValue="true"/>
<EditTextPreference
android:key="@string/pref_key_gps_min_time"
android:title="@string/pref_gps_min_time_title"
android:summary="@string/pref_gps_min_time_summary"
android:dialogTitle="@string/pref_gps_min_time_dialog_title"
android:defaultValue="@string/pref_gps_min_time_default_sec" />
android:key="@string/pref_key_gps_min_time"
android:title="@string/pref_gps_min_time_title"
android:summary="@string/pref_gps_min_time_summary"
android:dialogTitle="@string/pref_gps_min_time_dialog_title"
android:defaultValue="@string/pref_gps_min_time_default_sec"/>
<EditTextPreference
android:key="@string/pref_key_gps_min_distance"
android:title="@string/pref_gps_min_distance_title"
android:summary="@string/pref_gps_min_distance_summary"
android:dialogTitle="@string/pref_gps_min_distance_dialog_title"
android:defaultValue="@string/pref_gps_min_distance_default_meters" />
android:key="@string/pref_key_gps_min_distance"
android:title="@string/pref_gps_min_distance_title"
android:summary="@string/pref_gps_min_distance_summary"
android:dialogTitle="@string/pref_gps_min_distance_dialog_title"
android:defaultValue="@string/pref_gps_min_distance_default_meters"/>
<Preference
android:key="@string/pref_key_analyze_gps_accuracy"
android:title="@string/pref_analyze_gps_accuracy_title"
android:summary="@string/pref_analyze_gps_accuracy_summary" >
android:key="@string/pref_key_analyze_gps_accuracy"
android:title="@string/pref_analyze_gps_accuracy_title"
android:summary="@string/pref_analyze_gps_accuracy_summary">
</Preference>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_display_category_title"
android:key="@string/pref_key_display_category">
android:title="@string/pref_display_category_title"
android:key="@string/pref_key_display_category">
<CheckBoxPreference
android:key="@string/pref_key_keep_screen_on"
android:title="@string/pref_keep_screen_on_title"
android:summary="@string/pref_keep_screen_on_summary"
android:defaultValue="true" />
android:key="@string/pref_key_keep_screen_on"
android:title="@string/pref_keep_screen_on_title"
android:summary="@string/pref_keep_screen_on_summary"
android:defaultValue="true"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_about_category_title"
android:key="@string/pref_key_about_category">
<Preference
android:key="@string/pref_key_showed_v2_tutorial"
android:title="@string/pref_show_tutorial_title"
android:summary="@string/pref_show_tutorial_summary" />
android:title="@string/pref_about_category_title"
android:key="@string/pref_key_about_category">
<Preference
android:key="@string/pref_key_showed_v2_tutorial"
android:title="@string/pref_show_tutorial_title"
android:summary="@string/pref_show_tutorial_summary"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.espiandev.showcaseview"
android:versionCode="1"
android:versionName="1.0">
<application />
package="com.github.espiandev.showcaseview"
android:versionCode="1"
android:versionName="1.0">
<application/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8" />
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8"/>
</manifest>

View File

@@ -1,10 +1,19 @@
package com.github.espiandev.showcaseview;
import com.github.espiandev.showcaseview.anim.AnimationUtils;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.*;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.DynamicLayout;
@@ -13,12 +22,14 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Button;
import android.widget.RelativeLayout;
import com.github.espiandev.showcaseview.anim.AnimationUtils;
import java.lang.reflect.Field;
import static com.github.espiandev.showcaseview.anim.AnimationUtils.AnimationEndListener;
@@ -27,49 +38,81 @@ import static com.github.espiandev.showcaseview.anim.AnimationUtils.AnimationSta
/**
* A view which allows you to showcase areas of your app with an explanation.
*/
public class ShowcaseView extends RelativeLayout implements View.OnClickListener, View.OnTouchListener {
public class ShowcaseView extends RelativeLayout
implements View.OnClickListener, View.OnTouchListener {
public static final int TYPE_NO_LIMIT = 0;
public static final int TYPE_ONE_SHOT = 1;
public static final int INSERT_TO_DECOR = 0;
public static final int INSERT_TO_VIEW = 1;
public static final int ITEM_ACTION_HOME = 0;
public static final int ITEM_TITLE = 1;
public static final int ITEM_SPINNER = 2;
public static final int ITEM_ACTION_ITEM = 3;
public static final int ITEM_ACTION_OVERFLOW = 6;
private static final String PREFS_SHOWCASE_INTERNAL = "showcase_internal";
public static final int INNER_CIRCLE_RADIUS = 94;
private float showcaseX = -1;
private float showcaseY = -1;
private float showcaseRadius = -1;
private float metricScale = 1.0f;
private float legacyShowcaseX = -1;
private float legacyShowcaseY = -1;
private boolean isRedundant = false;
private boolean hasCustomClickListener = false;
private ConfigOptions mOptions;
private Paint mPaintTitle, mEraser;
private TextPaint mPaintDetail;
private int backColor;
private Drawable showcase;
private View mHandy;
private final Button mEndButton;
private OnShowcaseEventListener mEventListener;
private Rect voidedArea;
private String mTitleText, mSubText;
private int detailTextColor = -1;
private int titleTextColor = -1;
private DynamicLayout mDynamicTitleLayout;
private DynamicLayout mDynamicDetailLayout;
private float[] mBestTextPosition;
private boolean mAlteredText = false;
private final String buttonText;
private float scaleMultiplier = 1f;
public ShowcaseView(Context context) {
@@ -84,10 +127,14 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
super(context, attrs, defStyle);
// Get the attributes for the ShowcaseView
final TypedArray styled = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ShowcaseView, R.attr.showcaseViewStyle, R.style.ShowcaseView);
backColor = styled.getInt(R.styleable.ShowcaseView_sv_backgroundColor, Color.argb(128, 80, 80, 80));
final TypedArray styled = context.getTheme()
.obtainStyledAttributes(attrs, R.styleable.ShowcaseView, R.attr.showcaseViewStyle,
R.style.ShowcaseView);
backColor = styled
.getInt(R.styleable.ShowcaseView_sv_backgroundColor, Color.argb(128, 80, 80, 80));
detailTextColor = styled.getColor(R.styleable.ShowcaseView_sv_detailTextColor, Color.WHITE);
titleTextColor = styled.getColor(R.styleable.ShowcaseView_sv_titleTextColor, Color.parseColor("#49C0EC"));
titleTextColor = styled
.getColor(R.styleable.ShowcaseView_sv_titleTextColor, Color.parseColor("#49C0EC"));
buttonText = styled.getString(R.styleable.ShowcaseView_sv_buttonText);
styled.recycle();
@@ -100,7 +147,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
private void init() {
boolean hasShot = getContext().getSharedPreferences(PREFS_SHOWCASE_INTERNAL, Context.MODE_PRIVATE)
boolean hasShot = getContext()
.getSharedPreferences(PREFS_SHOWCASE_INTERNAL, Context.MODE_PRIVATE)
.getBoolean("hasShot" + getConfigOptions().showcaseId, false);
if (hasShot && mOptions.shotType == TYPE_ONE_SHOT) {
// The showcase has already been shot once, so we don't need to do anything
@@ -141,8 +189,11 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
lps.height = LayoutParams.WRAP_CONTENT;
lps.width = LayoutParams.WRAP_CONTENT;
mEndButton.setLayoutParams(lps);
mEndButton.setText(buttonText != null ? buttonText : getResources().getString(R.string.ok));
if (!hasCustomClickListener) mEndButton.setOnClickListener(this);
mEndButton.setText(
buttonText != null ? buttonText : getResources().getString(R.string.ok));
if (!hasCustomClickListener) {
mEndButton.setOnClickListener(this);
}
addView(mEndButton);
}
@@ -194,30 +245,35 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
invalidate();
}
public void setShowcaseItem(final int itemType, final int actionItemId, final Activity activity) {
public void setShowcaseItem(final int itemType, final int actionItemId,
final Activity activity) {
post(new Runnable() {
@Override
public void run() {
View homeButton = activity.findViewById(android.R.id.home);
if (homeButton == null) {
// Thanks to @hameno for this
int homeId = activity.getResources().getIdentifier("abs__home", "id", activity.getPackageName());
int homeId = activity.getResources()
.getIdentifier("abs__home", "id", activity.getPackageName());
if (homeId != 0) {
homeButton = activity.findViewById(homeId);
}
}
if (homeButton == null)
throw new RuntimeException("insertShowcaseViewWithType cannot be used when the theme " +
"has no ActionBar");
if (homeButton == null) {
throw new RuntimeException(
"insertShowcaseViewWithType cannot be used when the theme " +
"has no ActionBar");
}
ViewParent p = homeButton.getParent().getParent(); //ActionBarView
if (!p.getClass().getName().contains("ActionBarView")) {
String previousP = p.getClass().getName();
p = p.getParent();
String throwP = p.getClass().getName();
if (!p.getClass().getName().contains("ActionBarView"))
if (!p.getClass().getName().contains("ActionBarView")) {
throw new IllegalStateException("Cannot find ActionBarView for " +
"Activity, instead found " + previousP + " and " + throwP);
}
}
Class abv = p.getClass(); //ActionBarView class
@@ -255,8 +311,9 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
Field mObField = mAmp.getClass().getDeclaredField("mOverflowButton");
mObField.setAccessible(true);
View mOb = (View) mObField.get(mAmp);
if (mOb != null)
if (mOb != null) {
setShowcaseView(mOb);
}
} else {
// Want an ActionItem, so find it
Field mAmvField = mAmp.getClass().getSuperclass().getDeclaredField("mMenuView");
@@ -269,15 +326,18 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
// Have to get superclasses because mChildren is private
mChField = mAmv.getClass().getSuperclass().getSuperclass()
.getSuperclass().getSuperclass().getDeclaredField("mChildren");
} else
mChField = mAmv.getClass().getSuperclass().getSuperclass().getDeclaredField("mChildren");
} else {
mChField = mAmv.getClass().getSuperclass().getSuperclass()
.getDeclaredField("mChildren");
}
mChField.setAccessible(true);
Object[] mChs = (Object[]) mChField.get(mAmv);
for (Object mCh : mChs) {
if (mCh != null) {
View v = (View) mCh;
if (v.getId() == actionItemId)
if (v.getId() == actionItemId) {
setShowcaseView(v);
}
}
}
}
@@ -373,7 +433,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
return;
}
Bitmap b = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Bitmap b = Bitmap
.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
//Draw the semi-transparent background
@@ -406,20 +467,24 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
b = null;
if (!TextUtils.isEmpty(mTitleText) || !TextUtils.isEmpty(mSubText)) {
if (recalculateText)
if (recalculateText) {
mBestTextPosition = getBestTextPosition(canvas.getWidth(), canvas.getHeight());
}
if (!TextUtils.isEmpty(mTitleText)) {
//TODO: use a dynamic detail layout
canvas.drawText(mTitleText, mBestTextPosition[0], mBestTextPosition[1], mPaintTitle);
canvas.drawText(mTitleText, mBestTextPosition[0], mBestTextPosition[1],
mPaintTitle);
}
if (!TextUtils.isEmpty(mSubText)) {
canvas.save();
if (recalculateText)
if (recalculateText) {
mDynamicDetailLayout = new DynamicLayout(mSubText, mPaintDetail,
((Number) mBestTextPosition[2]).intValue(), Layout.Alignment.ALIGN_NORMAL,
((Number) mBestTextPosition[2]).intValue(),
Layout.Alignment.ALIGN_NORMAL,
1.2f, 1.0f, true);
}
canvas.translate(mBestTextPosition[0], mBestTextPosition[1] + 12 * metricScale);
mDynamicDetailLayout.draw(canvas);
canvas.restore();
@@ -436,18 +501,20 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
*
* @param canvasW width of the screen
* @param canvasH height of the screen
* @return
*/
private float[] getBestTextPosition(int canvasW, int canvasH) {
//if the width isn't much bigger than the voided area, just consider top & bottom
float spaceTop = voidedArea.top;
float spaceBottom = canvasH - voidedArea.bottom - 64 * metricScale; //64dip considers the OK button
float spaceBottom = canvasH - voidedArea.bottom
- 64 * metricScale; //64dip considers the OK button
//float spaceLeft = voidedArea.left;
//float spaceRight = canvasW - voidedArea.right;
//TODO: currently only considers above or below showcase, deal with left or right
return new float[]{24 * metricScale, spaceTop > spaceBottom ? 128 * metricScale : 24 * metricScale + voidedArea.bottom, canvasW - 48 * metricScale};
return new float[]{24 * metricScale,
spaceTop > spaceBottom ? 128 * metricScale : 24 * metricScale + voidedArea.bottom,
canvasW - 48 * metricScale};
}
@@ -479,8 +546,10 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
public void animateGesture(float offsetStartX, float offsetStartY, float offsetEndX, float offsetEndY) {
mHandy = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.handy, null);
public void animateGesture(float offsetStartX, float offsetStartY, float offsetEndX,
float offsetEndY) {
mHandy = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.handy, null);
addView(mHandy);
moveHand(offsetStartX, offsetStartY, offsetEndX, offsetEndY, new AnimationEndListener() {
@Override
@@ -490,7 +559,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
});
}
private void moveHand(float offsetStartX, float offsetStartY, float offsetEndX, float offsetEndY, AnimationEndListener listener) {
private void moveHand(float offsetStartX, float offsetStartY, float offsetEndX,
float offsetEndY, AnimationEndListener listener) {
AnimationUtils.createMovementAnimation(mHandy, showcaseX, showcaseY,
offsetStartX, offsetStartY,
offsetEndX, offsetEndY,
@@ -501,11 +571,13 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
public void onClick(View view) {
// If the type is set to one-shot, store that it has shot
if (mOptions.shotType == TYPE_ONE_SHOT) {
SharedPreferences internal = getContext().getSharedPreferences(PREFS_SHOWCASE_INTERNAL, Context.MODE_PRIVATE);
SharedPreferences internal = getContext()
.getSharedPreferences(PREFS_SHOWCASE_INTERNAL, Context.MODE_PRIVATE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
internal.edit().putBoolean("hasShot" + getConfigOptions().showcaseId, true).apply();
} else {
internal.edit().putBoolean("hasShot" + getConfigOptions().showcaseId, true).commit();
internal.edit().putBoolean("hasShot" + getConfigOptions().showcaseId, true)
.commit();
}
}
hide();
@@ -610,7 +682,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
* @return a View representing the ghostly hand
*/
public View getHand() {
final View mHandy = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.handy, null);
final View mHandy = ((LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.handy, null);
addView(mHandy);
AnimationUtils.hide(mHandy);
@@ -644,7 +717,9 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
private ConfigOptions getConfigOptions() {
// Make sure that this method never returns null
if (mOptions == null) return mOptions = new ConfigOptions();
if (mOptions == null) {
return mOptions = new ConfigOptions();
}
return mOptions;
}
@@ -658,11 +733,13 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
* @param options A set of options to customise the ShowcaseView
* @return the created ShowcaseView instance
*/
public static ShowcaseView insertShowcaseView(View viewToShowcase, Activity activity, String title,
String detailText, ConfigOptions options) {
public static ShowcaseView insertShowcaseView(View viewToShowcase, Activity activity,
String title,
String detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -684,10 +761,11 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
* @return the created ShowcaseView instance
*/
public static ShowcaseView insertShowcaseView(View viewToShowcase, Activity activity, int title,
int detailText, ConfigOptions options) {
int detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -698,8 +776,9 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
return sv;
}
public static ShowcaseView insertShowcaseView(int showcaseViewId, Activity activity, String title,
String detailText, ConfigOptions options) {
public static ShowcaseView insertShowcaseView(int showcaseViewId, Activity activity,
String title,
String detailText, ConfigOptions options) {
View v = activity.findViewById(showcaseViewId);
if (v != null) {
return insertShowcaseView(v, activity, title, detailText, options);
@@ -708,7 +787,7 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
public static ShowcaseView insertShowcaseView(int showcaseViewId, Activity activity, int title,
int detailText, ConfigOptions options) {
int detailText, ConfigOptions options) {
View v = activity.findViewById(showcaseViewId);
if (v != null) {
return insertShowcaseView(v, activity, title, detailText, options);
@@ -717,10 +796,11 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
public static ShowcaseView insertShowcaseView(float x, float y, Activity activity, String title,
String detailText, ConfigOptions options) {
String detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -732,10 +812,11 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
public static ShowcaseView insertShowcaseView(float x, float y, Activity activity, int title,
int detailText, ConfigOptions options) {
int detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -753,7 +834,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
/**
* Quickly insert a ShowcaseView into an Activity, highlighting an item.
*
* @param type the type of item to showcase (can be ITEM_ACTION_HOME, ITEM_TITLE_OR_SPINNER, ITEM_ACTION_ITEM or ITEM_ACTION_OVERFLOW)
* @param type the type of item to showcase (can be ITEM_ACTION_HOME,
* ITEM_TITLE_OR_SPINNER, ITEM_ACTION_ITEM or ITEM_ACTION_OVERFLOW)
* @param itemId the ID of an Action item to showcase (only required for ITEM_ACTION_ITEM
* @param activity Activity to insert the ShowcaseView into
* @param title Text to show as a title. Can be null.
@@ -761,10 +843,12 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
* @param options A set of options to customise the ShowcaseView
* @return the created ShowcaseView instance
*/
public static ShowcaseView insertShowcaseViewWithType(int type, int itemId, Activity activity, String title, String detailText, ConfigOptions options) {
public static ShowcaseView insertShowcaseViewWithType(int type, int itemId, Activity activity,
String title, String detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -778,7 +862,8 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
/**
* Quickly insert a ShowcaseView into an Activity, highlighting an item.
*
* @param type the type of item to showcase (can be ITEM_ACTION_HOME, ITEM_TITLE_OR_SPINNER, ITEM_ACTION_ITEM or ITEM_ACTION_OVERFLOW)
* @param type the type of item to showcase (can be ITEM_ACTION_HOME,
* ITEM_TITLE_OR_SPINNER, ITEM_ACTION_ITEM or ITEM_ACTION_OVERFLOW)
* @param itemId the ID of an Action item to showcase (only required for ITEM_ACTION_ITEM
* @param activity Activity to insert the ShowcaseView into
* @param title Text to show as a title. Can be null.
@@ -786,10 +871,12 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
* @param options A set of options to customise the ShowcaseView
* @return the created ShowcaseView instance
*/
public static ShowcaseView insertShowcaseViewWithType(int type, int itemId, Activity activity, int title, int detailText, ConfigOptions options) {
public static ShowcaseView insertShowcaseViewWithType(int type, int itemId, Activity activity,
int title, int detailText, ConfigOptions options) {
ShowcaseView sv = new ShowcaseView(activity);
if (options != null)
if (options != null) {
sv.setConfigOptions(options);
}
if (sv.getConfigOptions().insert == INSERT_TO_DECOR) {
((ViewGroup) activity.getWindow().getDecorView()).addView(sv);
} else {
@@ -805,10 +892,15 @@ public class ShowcaseView extends RelativeLayout implements View.OnClickListener
}
public static class ConfigOptions {
public boolean block = true, noButton = false;
public int showcaseId = 0;
public int shotType = TYPE_NO_LIMIT;
public int insert = INSERT_TO_DECOR;
public boolean hideOnClickOutside = false;
}

View File

@@ -16,7 +16,8 @@ public class ShowcaseViewBuilder {
}
public ShowcaseViewBuilder(Activity activity, int showcaseLayoutViewId) {
this.showcaseView = (ShowcaseView) activity.getLayoutInflater().inflate(showcaseLayoutViewId, null);
this.showcaseView = (ShowcaseView) activity.getLayoutInflater()
.inflate(showcaseLayoutViewId, null);
}
public ShowcaseViewBuilder setShowcaseView(View view) {
@@ -44,7 +45,8 @@ public class ShowcaseViewBuilder {
return this;
}
public ShowcaseViewBuilder animateGesture(float offsetStartX, float offsetStartY, float offsetEndX, float offsetEndY) {
public ShowcaseViewBuilder animateGesture(float offsetStartX, float offsetStartY,
float offsetEndX, float offsetEndY) {
showcaseView.animateGesture(offsetStartX, offsetStartY, offsetEndX, offsetEndY);
return this;
}
@@ -74,7 +76,7 @@ public class ShowcaseViewBuilder {
return this;
}
public ShowcaseView build(){
public ShowcaseView build() {
return showcaseView;
}
}

View File

@@ -10,8 +10,11 @@ import java.util.List;
public class ShowcaseViews {
private final List<ShowcaseView> views = new ArrayList<ShowcaseView>();
private final Activity activity;
private final int showcaseTemplateId;
private OnShowcaseAcknowledged showcaseAcknowledgedListener = new OnShowcaseAcknowledged() {
@Override
public void onShowCaseAcknowledged(ShowcaseView showcaseView) {
@@ -20,6 +23,7 @@ public class ShowcaseViews {
};
public interface OnShowcaseAcknowledged {
void onShowCaseAcknowledged(ShowcaseView showcaseView);
}
@@ -28,13 +32,15 @@ public class ShowcaseViews {
this.showcaseTemplateId = showcaseTemplateLayout;
}
public ShowcaseViews(Activity activity, int showcaseTemplateLayout, OnShowcaseAcknowledged acknowledgedListener) {
public ShowcaseViews(Activity activity, int showcaseTemplateLayout,
OnShowcaseAcknowledged acknowledgedListener) {
this(activity, showcaseTemplateLayout);
this.showcaseAcknowledgedListener = acknowledgedListener;
}
public void addView(ItemViewProperties properties) {
ShowcaseView showcaseView = new ShowcaseViewBuilder(activity, showcaseTemplateId).setShowcaseItem(properties.itemType, properties.id, activity)
ShowcaseView showcaseView = new ShowcaseViewBuilder(activity, showcaseTemplateId)
.setShowcaseItem(properties.itemType, properties.id, activity)
.setText(properties.titleResId, properties.messageResId)
.setShowcaseIndicatorScale(properties.scale)
.build();
@@ -42,7 +48,8 @@ public class ShowcaseViews {
views.add(showcaseView);
}
private View.OnClickListener createShowcaseViewDismissListener(final ShowcaseView showcaseView) {
private View.OnClickListener createShowcaseViewDismissListener(
final ShowcaseView showcaseView) {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -65,27 +72,36 @@ public class ShowcaseViews {
views.remove(0);
}
public boolean hasViews(){
public boolean hasViews() {
return !views.isEmpty();
}
public static class ItemViewProperties {
public static final int ID_SPINNER = 0;
public static final int ID_TITLE = 1;
public static final int ID_OVERFLOW = 2;
private static final float DEFAULT_SCALE = 1f;
protected final int titleResId;
protected final int messageResId;
protected final int id;
protected final int itemType;
protected final float scale;
public ItemViewProperties(int id, int titleResId, int messageResId, int itemType) {
this(id, titleResId, messageResId, itemType, DEFAULT_SCALE);
}
public ItemViewProperties(int id, int titleResId, int messageResId, int itemType, float scale) {
public ItemViewProperties(int id, int titleResId, int messageResId, int itemType,
float scale) {
this.id = id;
this.titleResId = titleResId;
this.messageResId = messageResId;

View File

@@ -1,28 +1,36 @@
package com.github.espiandev.showcaseview.anim;
import android.os.Handler;
import android.view.View;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.view.ViewHelper;
import android.os.Handler;
import android.view.View;
public class AnimationUtils {
private static final int DEFAULT_DURATION = 300;
private static final String ALPHA = "alpha";
private static final float INVISIBLE = 0f;
private static final float VISIBLE = 1f;
private static final String COORD_X = "x";
private static final String COORD_Y = "y";
private static final int INSTANT = 0;
public interface AnimationStartListener {
void onAnimationStart();
}
public interface AnimationEndListener {
void onAnimationEnd();
}
@@ -38,11 +46,13 @@ public class AnimationUtils {
ViewHelper.setAlpha(view, INVISIBLE);
}
public static ObjectAnimator createFadeInAnimation(Object target, final AnimationStartListener listener) {
public static ObjectAnimator createFadeInAnimation(Object target,
final AnimationStartListener listener) {
return createFadeInAnimation(target, DEFAULT_DURATION, listener);
}
public static ObjectAnimator createFadeInAnimation(Object target, int duration, final AnimationStartListener listener) {
public static ObjectAnimator createFadeInAnimation(Object target, int duration,
final AnimationStartListener listener) {
ObjectAnimator oa = ObjectAnimator.ofFloat(target, ALPHA, VISIBLE);
oa.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
@@ -65,11 +75,13 @@ public class AnimationUtils {
return oa;
}
public static ObjectAnimator createFadeOutAnimation(Object target, final AnimationEndListener listener) {
public static ObjectAnimator createFadeOutAnimation(Object target,
final AnimationEndListener listener) {
return createFadeOutAnimation(target, DEFAULT_DURATION, listener);
}
public static ObjectAnimator createFadeOutAnimation(Object target, int duration, final AnimationEndListener listener) {
public static ObjectAnimator createFadeOutAnimation(Object target, int duration,
final AnimationEndListener listener) {
ObjectAnimator oa = ObjectAnimator.ofFloat(target, ALPHA, INVISIBLE);
oa.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
@@ -93,18 +105,23 @@ public class AnimationUtils {
}
public static AnimatorSet createMovementAnimation(View view, float canvasX, float canvasY,
float offsetStartX, float offsetStartY,
float offsetEndX, float offsetEndY,
final AnimationEndListener listener) {
float offsetStartX, float offsetStartY,
float offsetEndX, float offsetEndY,
final AnimationEndListener listener) {
ViewHelper.setAlpha(view, INVISIBLE);
ObjectAnimator alphaIn = ObjectAnimator.ofFloat(view, ALPHA, INVISIBLE, VISIBLE).setDuration(500);
ObjectAnimator alphaIn = ObjectAnimator.ofFloat(view, ALPHA, INVISIBLE, VISIBLE)
.setDuration(500);
ObjectAnimator setUpX = ObjectAnimator.ofFloat(view, COORD_X, canvasX + offsetStartX).setDuration(INSTANT);
ObjectAnimator setUpY = ObjectAnimator.ofFloat(view, COORD_Y, canvasY + offsetStartY).setDuration(INSTANT);
ObjectAnimator setUpX = ObjectAnimator.ofFloat(view, COORD_X, canvasX + offsetStartX)
.setDuration(INSTANT);
ObjectAnimator setUpY = ObjectAnimator.ofFloat(view, COORD_Y, canvasY + offsetStartY)
.setDuration(INSTANT);
ObjectAnimator moveX = ObjectAnimator.ofFloat(view, COORD_X, canvasX + offsetEndX).setDuration(1000);
ObjectAnimator moveY = ObjectAnimator.ofFloat(view, COORD_Y, canvasY + offsetEndY).setDuration(1000);
ObjectAnimator moveX = ObjectAnimator.ofFloat(view, COORD_X, canvasX + offsetEndX)
.setDuration(1000);
ObjectAnimator moveY = ObjectAnimator.ofFloat(view, COORD_Y, canvasY + offsetEndY)
.setDuration(1000);
moveX.setStartDelay(1000);
moveY.setStartDelay(1000);
@@ -127,7 +144,8 @@ public class AnimationUtils {
}
public static AnimatorSet createMovementAnimation(View view, float x, float y) {
ObjectAnimator alphaIn = ObjectAnimator.ofFloat(view, ALPHA, INVISIBLE, VISIBLE).setDuration(500);
ObjectAnimator alphaIn = ObjectAnimator.ofFloat(view, ALPHA, INVISIBLE, VISIBLE)
.setDuration(500);
ObjectAnimator setUpX = ObjectAnimator.ofFloat(view, COORD_X, x).setDuration(INSTANT);
ObjectAnimator setUpY = ObjectAnimator.ofFloat(view, COORD_Y, y).setDuration(INSTANT);

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/hand" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/hand"/>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/ShowcaseButton"
android:text="@string/ok"
android:id="@id/showcase_button" />
style="@style/ShowcaseButton"
android:text="@string/ok"
android:id="@id/showcase_button"/>

View File

@@ -1,15 +1,15 @@
<resources>
<declare-styleable name="ShowcaseView">
<attr name="sv_backgroundColor" format="color|reference" />
<attr name="sv_detailTextColor" format="color|reference" />
<attr name="sv_titleTextColor" format="color|reference" />
<attr name="sv_buttonBackgroundColor" format="color|reference" />
<attr name="sv_buttonForegroundColor" format="color|reference" />
<attr name="sv_buttonText" format="string|reference" />
<attr name="sv_backgroundColor" format="color|reference"/>
<attr name="sv_detailTextColor" format="color|reference"/>
<attr name="sv_titleTextColor" format="color|reference"/>
<attr name="sv_buttonBackgroundColor" format="color|reference"/>
<attr name="sv_buttonForegroundColor" format="color|reference"/>
<attr name="sv_buttonText" format="string|reference"/>
</declare-styleable>
<declare-styleable name="CustomTheme">
<attr name="showcaseViewStyle" format="reference" />
<attr name="showcaseViewStyle" format="reference"/>
</declare-styleable>
</resources>

View File

@@ -1,5 +1,5 @@
<resources>
<item type="id" name="showcase_button" />
<item type="id" name="showcase_title_text" />
<item type="id" name="showcase_sub_text" />
<item type="id" name="showcase_button"/>
<item type="id" name="showcase_title_text"/>
<item type="id" name="showcase_sub_text"/>
</resources>