├── .gitignore
├── GeofenceExample.apk
├── README.md
├── Screenshot_2015-02-05-10-06-46.png
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── androidfu
│ │ └── example
│ │ └── geofences
│ │ └── ApplicationTest.java
│ ├── debug
│ └── AndroidManifest.xml
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── androidfu
│ │ └── example
│ │ └── geofences
│ │ ├── GeofenceTransitionReceiver.java
│ │ ├── MapsActivity.java
│ │ └── MyPlaces.java
│ └── res
│ ├── drawable-hdpi-v11
│ └── ic_stat_action_room.png
│ ├── drawable-hdpi
│ ├── ic_launcher.png
│ └── ic_stat_action_room.png
│ ├── drawable-mdpi-v11
│ └── ic_stat_action_room.png
│ ├── drawable-mdpi
│ ├── ic_launcher.png
│ └── ic_stat_action_room.png
│ ├── drawable-xhdpi-v11
│ └── ic_stat_action_room.png
│ ├── drawable-xhdpi
│ ├── ic_launcher.png
│ └── ic_stat_action_room.png
│ ├── drawable-xxhdpi-v11
│ └── ic_stat_action_room.png
│ ├── drawable-xxhdpi
│ ├── ic_heart.png
│ ├── ic_home.png
│ ├── ic_launcher.png
│ ├── ic_palm_tree.png
│ ├── ic_reset.png
│ └── ic_stat_action_room.png
│ ├── drawable-xxxhdpi
│ └── ic_launcher.png
│ ├── layout
│ └── activity_maps.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── colors.xml
│ ├── google_maps_api.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 |
--------------------------------------------------------------------------------
/GeofenceExample.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/GeofenceExample.apk
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GeofenceExample
2 | 1. Clone the project
3 | 1. Add the following strings resource with your Google Maps Key
4 |
5 | `{your key goes here}`
6 |
7 | _NOTE: Works best from an emulator as any other application working with location can interfere with your Mock location_
8 |
9 | Screenshot(s)
10 | =============
11 | 
12 |
13 | Videos(s)
14 | =============
15 | [](http://youtu.be/NEmApV0IaAs)
16 |
17 | Download(s)
18 | =============
19 | [GeofenceExample.apk Download](/GeofenceExample.apk?raw=true)
20 |
--------------------------------------------------------------------------------
/Screenshot_2015-02-05-10-06-46.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/Screenshot_2015-02-05-10-06-46.png
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "21.1.2"
6 |
7 | defaultConfig {
8 | applicationId "com.androidfu.example.geofences"
9 | minSdkVersion 15
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | applicationVariants.all { variant ->
23 | variant.outputs.each { output ->
24 | def newApkName
25 | newApkName = "GeofenceExample.apk";
26 | output.outputFile = new File("${project.rootDir}", newApkName);
27 | }
28 | }
29 | }
30 |
31 | dependencies {
32 | compile fileTree(dir: 'libs', include: ['*.jar'])
33 | compile 'com.google.android.gms:play-services:6.5.87'
34 | compile 'com.android.support:appcompat-v7:22.+'
35 | }
36 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/bmote/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/androidfu/example/geofences/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.androidfu.example.geofences;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
21 |
24 |
27 |
28 |
31 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/androidfu/example/geofences/GeofenceTransitionReceiver.java:
--------------------------------------------------------------------------------
1 | package com.androidfu.example.geofences;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationManager;
5 | import android.app.PendingIntent;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.graphics.Color;
9 | import android.support.v4.app.NotificationCompat;
10 | import android.support.v4.content.WakefulBroadcastReceiver;
11 | import android.util.Log;
12 | import android.widget.Toast;
13 |
14 | import com.google.android.gms.location.Geofence;
15 | import com.google.android.gms.location.GeofencingEvent;
16 |
17 | public class GeofenceTransitionReceiver extends WakefulBroadcastReceiver {
18 |
19 | public static final String TAG = GeofenceTransitionReceiver.class.getSimpleName();
20 |
21 | private Context context;
22 |
23 | public GeofenceTransitionReceiver() {
24 | }
25 |
26 | @Override
27 | public void onReceive(Context context, Intent intent) {
28 | Log.v(TAG, "onReceive(context, intent)");
29 | this.context = context;
30 | GeofencingEvent event = GeofencingEvent.fromIntent(intent);
31 | if(event != null){
32 | if(event.hasError()){
33 | onError(event.getErrorCode());
34 | } else {
35 | int transition = event.getGeofenceTransition();
36 | if(transition == Geofence.GEOFENCE_TRANSITION_ENTER || transition == Geofence.GEOFENCE_TRANSITION_DWELL || transition == Geofence.GEOFENCE_TRANSITION_EXIT){
37 | String[] geofenceIds = new String[event.getTriggeringGeofences().size()];
38 | for (int index = 0; index < event.getTriggeringGeofences().size(); index++) {
39 | geofenceIds[index] = event.getTriggeringGeofences().get(index).getRequestId();
40 | }
41 | if (transition == Geofence.GEOFENCE_TRANSITION_ENTER || transition == Geofence.GEOFENCE_TRANSITION_DWELL) {
42 | onEnteredGeofences(geofenceIds);
43 | } else {
44 | onExitedGeofences(geofenceIds);
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
51 | protected void onEnteredGeofences(String[] geofenceIds) {
52 | for (String fenceId : geofenceIds) {
53 | Toast.makeText(context, String.format("Entered this fence: %1$s", fenceId), Toast.LENGTH_SHORT).show();
54 | Log.i(TAG, String.format("Entered this fence: %1$s", fenceId));
55 | createNotification(fenceId, "Entered");
56 | }
57 | }
58 |
59 | protected void onExitedGeofences(String[] geofenceIds){
60 | for (String fenceId : geofenceIds) {
61 | Toast.makeText(context, String.format("Exited this fence: %1$s", fenceId), Toast.LENGTH_SHORT).show();
62 | Log.i(TAG, String.format("Exited this fence: %1$s", fenceId));
63 | createNotification(fenceId, "Exited");
64 | }
65 | }
66 |
67 | protected void onError(int errorCode){
68 | Toast.makeText(context, String.format("onError(%1$d)", errorCode), Toast.LENGTH_SHORT).show();
69 | Log.e(TAG, String.format("onError(%1$d)", errorCode));
70 | }
71 |
72 | /**
73 | * Create our notification.
74 | *
75 | * @param fenceId the name of the Geofence
76 | * @param fenceState Entered, Exited or Dwell
77 | */
78 | private void createNotification(String fenceId, String fenceState) {
79 | NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
80 | notificationBuilder.setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL);
81 | notificationBuilder
82 | .setContentText(fenceId)
83 | .setContentTitle(String.format("Fence %1$s", fenceState))
84 | .setSmallIcon(R.drawable.ic_stat_action_room)
85 | .setColor(Color.argb(0x55, 0x00, 0x00, 0xff))
86 | .setTicker(String.format("%1$s Fence: %2$s", fenceState, fenceId));
87 | Intent notificationIntent = new Intent(context, MapsActivity.class);
88 | notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
89 | notificationIntent.setAction(Intent.ACTION_MAIN);
90 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
91 | PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
92 | notificationBuilder.setContentIntent(pendingIntent);
93 | notificationManager.notify(R.id.notification, notificationBuilder.build());
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/androidfu/example/geofences/MapsActivity.java:
--------------------------------------------------------------------------------
1 | package com.androidfu.example.geofences;
2 |
3 | import android.app.PendingIntent;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Color;
7 | import android.location.Criteria;
8 | import android.location.Location;
9 | import android.location.LocationManager;
10 | import android.os.Build;
11 | import android.os.Bundle;
12 | import android.os.SystemClock;
13 | import android.support.v4.app.FragmentActivity;
14 | import android.text.TextUtils;
15 | import android.util.Log;
16 | import android.view.View;
17 | import android.view.WindowManager;
18 | import android.widget.ImageButton;
19 | import android.widget.Toast;
20 |
21 | import com.google.android.gms.common.ConnectionResult;
22 | import com.google.android.gms.common.api.GoogleApiClient;
23 | import com.google.android.gms.common.api.PendingResult;
24 | import com.google.android.gms.common.api.ResultCallback;
25 | import com.google.android.gms.common.api.Status;
26 | import com.google.android.gms.location.Geofence;
27 | import com.google.android.gms.location.LocationServices;
28 | import com.google.android.gms.maps.CameraUpdateFactory;
29 | import com.google.android.gms.maps.GoogleMap;
30 | import com.google.android.gms.maps.SupportMapFragment;
31 | import com.google.android.gms.maps.model.BitmapDescriptorFactory;
32 | import com.google.android.gms.maps.model.CircleOptions;
33 | import com.google.android.gms.maps.model.LatLng;
34 | import com.google.android.gms.maps.model.MarkerOptions;
35 |
36 | import java.lang.reflect.Method;
37 | import java.util.ArrayList;
38 | import java.util.List;
39 |
40 | public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener, ResultCallback {
41 |
42 | public static final String TAG = MapsActivity.class.getSimpleName();
43 |
44 | private static final long LOCATION_ITERATION_PAUSE_TIME = 1000;
45 | private static final int NUMBER_OF_LOCATION_ITERATIONS = 10;
46 |
47 | private GoogleMap googleMap; // Might be null if Google Play services APK is not available.
48 | private MyPlaces happyPlace;
49 | private MyPlaces home;
50 | private List myFences = new ArrayList<>();
51 | private GoogleApiClient googleApiClient;
52 | private PendingIntent geofencePendingIntent;
53 | private UpdateLocationRunnable updateLocationRunnable;
54 | private LocationManager locationManager;
55 | private int marker = 0;
56 | private Location lastLocation;
57 |
58 | @Override
59 | protected void onCreate(Bundle savedInstanceState) {
60 | super.onCreate(savedInstanceState);
61 | setContentView(R.layout.activity_maps);
62 |
63 | ImageButton happyPlaceBtn = (ImageButton) findViewById(R.id.ib_happy_place);
64 | happyPlaceBtn.setOnClickListener(this);
65 |
66 | ImageButton homeBtn = (ImageButton) findViewById(R.id.ib_home);
67 | homeBtn.setOnClickListener(this);
68 |
69 | ImageButton resetBtn = (ImageButton) findViewById(R.id.ib_reset);
70 | resetBtn.setOnClickListener(this);
71 |
72 | setUpMapIfNeeded();
73 | }
74 |
75 | /**
76 | * Called when a view has been clicked.
77 | *
78 | * @param v The view that was clicked.
79 | */
80 | @Override
81 | public void onClick(View v) {
82 |
83 | MyPlaces place;
84 | switch (v.getId()) {
85 | case R.id.ib_happy_place:
86 | Toast.makeText(this, "You Clicked Happy Place", Toast.LENGTH_SHORT).show();
87 | place = happyPlace;
88 | moveToLocation(place);
89 | break;
90 | case R.id.ib_home:
91 | Toast.makeText(this, "You Clicked Home", Toast.LENGTH_SHORT).show();
92 | place = home;
93 | moveToLocation(place);
94 | break;
95 | case R.id.ib_reset:
96 | Toast.makeText(this, "Resetting Our Map", Toast.LENGTH_SHORT).show();
97 | if (updateLocationRunnable != null) {
98 | updateLocationRunnable.interrupt();
99 | }
100 | googleApiClient.disconnect();
101 | googleMap.clear();
102 | myFences.clear();
103 | setUpMap();
104 | break;
105 | }
106 | }
107 |
108 | @Override
109 | protected void onResume() {
110 | super.onResume();
111 |
112 | setUpMapIfNeeded();
113 |
114 | this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
115 |
116 | Log.i(TAG, "Setup MOCK Location Providers");
117 | locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
118 |
119 | Log.i(TAG, "GPS Provider");
120 | locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, true, false, false, false, false, false, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
121 | locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
122 |
123 | Log.i(TAG, "Network Provider");
124 | locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, true, false, true, false, false, false, false, Criteria.POWER_MEDIUM, Criteria.ACCURACY_FINE);
125 | locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
126 | }
127 |
128 | @Override
129 | protected void onPause() {
130 | this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
131 |
132 | // Interrupt our runnable if we're going into the background or exiting
133 | if (updateLocationRunnable != null) {
134 | updateLocationRunnable.interrupt();
135 | }
136 |
137 | Log.i(TAG, "Cleanup Our Fields");
138 | locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
139 | locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
140 | locationManager = null;
141 | updateLocationRunnable = null;
142 |
143 | super.onPause();
144 | }
145 |
146 | @Override
147 | protected void onStop() {
148 | googleApiClient.disconnect();
149 | super.onStop();
150 | }
151 |
152 | /**
153 | * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
154 | * installed) and the map has not already been instantiated.. This will ensure that we only ever
155 | * call {@link #setUpMap()} once when {@link #googleMap} is not null.
156 | *
157 | * If it isn't installed {@link SupportMapFragment} (and
158 | * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
159 | * install/update the Google Play services APK on their device.
160 | *
161 | * A user can return to this FragmentActivity after following the prompt and correctly
162 | * installing/updating/enabling the Google Play services. Since the FragmentActivity may not
163 | * have been completely destroyed during this process (it is likely that it would only be
164 | * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this
165 | * method in {@link #onResume()} to guarantee that it will be called.
166 | */
167 | private void setUpMapIfNeeded() {
168 | // Do a null check to confirm that we have not already instantiated the map.
169 | if (googleMap == null) {
170 | // Try to obtain the map from the SupportMapFragment.
171 | googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
172 | // Check if we were successful in obtaining the map.
173 | if (googleMap != null) {
174 | setUpMap();
175 | }
176 | }
177 | }
178 |
179 | /**
180 | * This is where we can add markers or lines, add listeners or move the camera.
181 | *
182 | * This should only be called once and when we are sure that {@link #googleMap} is not null.
183 | */
184 | private void setUpMap() {
185 | googleMap.setBuildingsEnabled(true);
186 |
187 | // PRES 1
188 | /*
189 | 1. Create a "Place" that will become a Geofence
190 | 2. Add a place marker on our Map
191 | 3. Add our place to our list of Geofences
192 | 4. Repeat for each place
193 | */
194 |
195 | // Add a place with a Geofence
196 | happyPlace = new MyPlaces("Pier @ Folly Beach", "This is my Happy Place!", new LatLng(32.652411, -79.938063), 10000, 10, R.drawable.ic_palm_tree);
197 | addPlaceMarker(happyPlace);
198 | addFence(happyPlace);
199 |
200 | // Add a place with a Geofence
201 | // Work 39.3336585, -84.3146718
202 | // Home 39.2697455, -84.269921
203 | home = new MyPlaces("Home", "This is where I live.", new LatLng(39.3336585, -84.3146718), 10000, 10, R.drawable.ic_home);
204 | addPlaceMarker(home);
205 | addFence(home);
206 |
207 | // Add a place w/o a Geofence
208 | MyPlaces charleston = new MyPlaces("Charleston, SC", "This is where I want to live!", new LatLng(32.8210454, -79.9704779), 0, 10, R.drawable.ic_heart);
209 | addPlaceMarker(charleston);
210 | addFence(charleston);
211 |
212 | /*
213 | After all your places have been created and markers added you can monitor your fences.
214 | */
215 | monitorFences(myFences);
216 |
217 | googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
218 | @Override
219 | public void onMapClick(LatLng latLng) {
220 |
221 | if (updateLocationRunnable != null && updateLocationRunnable.isAlive() && !updateLocationRunnable.isInterrupted()) {
222 | updateLocationRunnable.interrupt();
223 | }
224 | updateLocationRunnable = new UpdateLocationRunnable(locationManager, latLng);
225 | updateLocationRunnable.start();
226 |
227 | MyPlaces touchedPlace = new MyPlaces(String.format("Marker %1$d", ++marker), "", latLng, 65, 12, 0);
228 | addPlaceMarker(touchedPlace);
229 | }
230 | });
231 | }
232 |
233 | /**
234 | * Add a map marker at the place specified.
235 | *
236 | * @param place the place to take action on
237 | */
238 | private void addPlaceMarker(MyPlaces place) {
239 | MarkerOptions markerOptions = new MarkerOptions();
240 | markerOptions.position(place.getCoordinates())
241 | .title(place.getTitle());
242 | if (!TextUtils.isEmpty(place.getSnippet())) {
243 | markerOptions.snippet(place.getSnippet());
244 | }
245 | if (place.getIconResourceId() > 0) {
246 | markerOptions.icon(BitmapDescriptorFactory.fromResource(place.getIconResourceId()));
247 | }
248 | googleMap.addMarker(markerOptions);
249 | drawGeofenceAroundTarget(place);
250 | }
251 |
252 | /**
253 | * If our place has a fence radius greater than 0 then draw a circle around it.
254 | *
255 | * @param place the place to take action on
256 | */
257 | private void drawGeofenceAroundTarget(MyPlaces place) {
258 | if (place.getFenceRadius() <= 0) {
259 | // Nothing to draw
260 | return;
261 | }
262 | CircleOptions circleOptions = new CircleOptions();
263 | circleOptions.center(place.getCoordinates());
264 | circleOptions.fillColor(Color.argb(0x55, 0x00, 0x00, 0xff));
265 | circleOptions.strokeColor(Color.argb(0xaa, 0x00, 0x00, 0xff));
266 | circleOptions.radius(place.getFenceRadius());
267 | googleMap.addCircle(circleOptions);
268 | }
269 |
270 | /**
271 | * Update our map's location to the place specified.
272 | *
273 | * @param place the place to take action on
274 | */
275 | private void moveToLocation(final MyPlaces place) {
276 | // Move the camera instantly to "place" with a zoom of 5.
277 | if (place.getTitle().equals("Charleston, SC")) {
278 | googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getCoordinates(), place.getDefaultZoomLevel()));
279 | }
280 |
281 | // Fly to our new location and then set the correct zoom level for the given place.
282 | googleMap.animateCamera(CameraUpdateFactory.newLatLng(place.getCoordinates()), new GoogleMap.CancelableCallback() {
283 | @Override
284 | public void onFinish() {
285 | googleMap.animateCamera(CameraUpdateFactory.zoomTo(place.getDefaultZoomLevel()), 2000, null);
286 | }
287 |
288 | @Override
289 | public void onCancel() {
290 | // Nothing to see here.
291 | }
292 | });
293 | }
294 |
295 | /**
296 | * If our place has a fence radius > 0 then add it to our monitored fences.
297 | *
298 | * @param place the place to take action on
299 | */
300 | private void addFence(MyPlaces place) {
301 | if (place.getFenceRadius() <= 0) {
302 | // Nothing to monitor
303 | return;
304 | }
305 | Geofence geofence = new Geofence.Builder()
306 | .setCircularRegion(place.getCoordinates().latitude, place.getCoordinates().longitude, place.getFenceRadius())
307 | .setRequestId(place.getTitle()) // every fence must have an ID
308 | .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) // can also have DWELL
309 | .setExpirationDuration(Geofence.NEVER_EXPIRE) // how long do we care about this geofence?
310 | //.setLoiteringDelay(60000) // 1 min.
311 | .build();
312 | myFences.add(geofence);
313 | }
314 |
315 | /**
316 | * Connect our GoogleApiClient so we can begin monitoring our fences.
317 | *
318 | * @param fences our list of Geofences to monitor
319 | */
320 | private void monitorFences(List fences) {
321 | if (fences.isEmpty()) {
322 | throw new RuntimeException("No fences to monitor. Call addPlaceMarker() First.");
323 | }
324 | // PRES 2
325 | googleApiClient = new GoogleApiClient.Builder(this)
326 | .addApi(LocationServices.API)
327 | .addConnectionCallbacks(this)
328 | .addOnConnectionFailedListener(this)
329 | .build();
330 | googleApiClient.connect();
331 | }
332 |
333 | @Override
334 | public void onConnected(Bundle bundle) {
335 | /*
336 | TODO
337 | 1. Display a spinner in the progress bar while we're waiting for location
338 | 2. When connected & not null update map position to location
339 | 3. If location null try again once every 10 seconds until we get an answer or quit after x minutes
340 | 4. ?
341 | */
342 | Toast.makeText(this, "GoogleApiClient Connected", Toast.LENGTH_SHORT).show();
343 | lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
344 | String lastLocationMessage;
345 | if (lastLocation == null) {
346 | lastLocationMessage = "Last Location is NULL";
347 | moveToLocation(home);
348 | } else {
349 | lastLocationMessage = String.format("Last Location (%1$s, %2$s)", lastLocation.getLatitude(), lastLocation.getLongitude());
350 | moveToLocation(new MyPlaces("Last Location", "I am here.", new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 0, 13, 0));
351 | }
352 | Toast.makeText(this, lastLocationMessage, Toast.LENGTH_SHORT).show();
353 | // PRES 3
354 | geofencePendingIntent = getRequestPendingIntent();
355 | PendingResult result = LocationServices.GeofencingApi.addGeofences(googleApiClient, myFences, geofencePendingIntent);
356 | result.setResultCallback(this);
357 | }
358 |
359 | @Override
360 | public void onConnectionSuspended(int i) {
361 | Toast.makeText(this, "GoogleApiClient Connection Suspended", Toast.LENGTH_SHORT).show();
362 | }
363 |
364 | @Override
365 | public void onConnectionFailed(ConnectionResult connectionResult) {
366 | Toast.makeText(this, "GoogleApiClient Connection Failed", Toast.LENGTH_SHORT).show();
367 | }
368 |
369 | @Override
370 | public void onResult(Status status) {
371 | String toastMessage;
372 | // PRES 4
373 | if (status.isSuccess()) {
374 | toastMessage = "Success: We Are Monitoring Our Fences";
375 | } else {
376 | toastMessage = "Error: We Are NOT Monitoring Our Fences";
377 | }
378 | Toast.makeText(this, toastMessage, Toast.LENGTH_SHORT).show();
379 | }
380 |
381 | /**
382 | * Returns the current PendingIntent to the caller.
383 | *
384 | * @return The PendingIntent used to create the current set of geofences
385 | */
386 | public PendingIntent getRequestPendingIntent() {
387 | return createRequestPendingIntent();
388 | }
389 |
390 | /**
391 | * Get a PendingIntent to send with the request to add Geofences. Location
392 | * Services issues the Intent inside this PendingIntent whenever a geofence
393 | * transition occurs for the current list of geofences.
394 | *
395 | * @return A PendingIntent for the IntentService that handles geofence
396 | * transitions.
397 | */
398 | private PendingIntent createRequestPendingIntent() {
399 | if (geofencePendingIntent != null) {
400 | return geofencePendingIntent;
401 | } else {
402 | Intent intent = new Intent(this, GeofenceTransitionReceiver.class);
403 | intent.setAction("geofence_transition_action");
404 | return PendingIntent.getBroadcast(this, R.id.geofence_transition_intent, intent, PendingIntent.FLAG_UPDATE_CURRENT);
405 | }
406 | }
407 |
408 |
409 | // /////////////////////////////////////////////////////////////////////////////////////////
410 | // // UpdateLocationRunnable //
411 | // /////////////////////////////////////////////////////////////////////////////////////////
412 |
413 | private Location createMockLocation(String locationProvider, double latitude, double longitude) {
414 | Location location = new Location(locationProvider);
415 | location.setLatitude(latitude);
416 | location.setLongitude(longitude);
417 | location.setAccuracy(1.0f);
418 | location.setTime(System.currentTimeMillis());
419 | /*
420 | setElapsedRealtimeNanos() was added in API 17
421 | */
422 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
423 | location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
424 | }
425 | try {
426 | Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
427 | if (locationJellyBeanFixMethod != null) {
428 | locationJellyBeanFixMethod.invoke(location);
429 | }
430 | } catch (Exception e) {
431 | // There's no action to take here. This is a fix for Jelly Bean and no reason to report a failure.
432 | }
433 | return location;
434 | }
435 |
436 |
437 | // /////////////////////////////////////////////////////////////////////////////////////////
438 | // // CreateMockLocation //
439 | // /////////////////////////////////////////////////////////////////////////////////////////
440 |
441 | class UpdateLocationRunnable extends Thread {
442 |
443 | private final LocationManager locMgr;
444 | private final LatLng latlng;
445 | Location mockGpsLocation;
446 | Location mockNetworkLocation;
447 |
448 | UpdateLocationRunnable(LocationManager locMgr, LatLng latlng) {
449 | this.locMgr = locMgr;
450 | this.latlng = latlng;
451 | }
452 |
453 | /**
454 | * Starts executing the active part of the class' code. This method is
455 | * called when a thread is started that has been created with a class which
456 | * implements {@code Runnable}.
457 | */
458 | @Override
459 | public void run() {
460 | try {
461 | Log.i(TAG, String.format("Setting Mock Location to: %1$s, %2$s", latlng.latitude, latlng.longitude));
462 | /*
463 | Location can be finicky. Iterate over our desired location every second for
464 | NUMBER_OF_LOCATION_ITERATIONS seconds to help it figure out where we want it to
465 | be.
466 | */
467 | for (int i = 0; !isInterrupted() && i <= NUMBER_OF_LOCATION_ITERATIONS; i++) {
468 | mockGpsLocation = createMockLocation(LocationManager.GPS_PROVIDER, latlng.latitude, latlng.longitude);
469 | locMgr.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockGpsLocation);
470 | mockNetworkLocation = createMockLocation(LocationManager.NETWORK_PROVIDER, latlng.latitude, latlng.longitude);
471 | locMgr.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, mockNetworkLocation);
472 | Thread.sleep(LOCATION_ITERATION_PAUSE_TIME);
473 | }
474 | } catch (InterruptedException e) {
475 | Log.i(TAG, "Interrupted.");
476 | // Do nothing. We expect this to happen when location is successfully updated.
477 | } finally {
478 | Log.i(TAG, "Done moving location.");
479 | }
480 | }
481 | }
482 | }
483 |
--------------------------------------------------------------------------------
/app/src/main/java/com/androidfu/example/geofences/MyPlaces.java:
--------------------------------------------------------------------------------
1 | package com.androidfu.example.geofences;
2 |
3 | import com.google.android.gms.maps.model.LatLng;
4 |
5 | /**
6 | * Created by bmote on 2/4/15.
7 | */
8 | public class MyPlaces {
9 | private String title;
10 | private String snippet;
11 | private LatLng coordinates;
12 | private float fenceRadius;
13 | private int iconResourceId;
14 | private float defaultZoomLevel;
15 |
16 | public MyPlaces(String title, String snippet, LatLng coordinates, float fenceRadius, int defaultZoomLevel, int iconResourceId) {
17 | this.title = title;
18 | this.snippet = snippet;
19 | this.coordinates = coordinates;
20 | this.fenceRadius = fenceRadius;
21 | this.defaultZoomLevel = defaultZoomLevel;
22 | this.iconResourceId = iconResourceId;
23 | }
24 |
25 | public String getTitle() {
26 | return title;
27 | }
28 |
29 | public String getSnippet() {
30 | return snippet;
31 | }
32 |
33 | public LatLng getCoordinates() {
34 | return coordinates;
35 | }
36 |
37 | public float getFenceRadius() {
38 | return fenceRadius;
39 | }
40 |
41 | public float getDefaultZoomLevel() {
42 | return defaultZoomLevel;
43 | }
44 |
45 | public int getIconResourceId() {
46 | return iconResourceId;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi-v11/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-hdpi-v11/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-hdpi/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi-v11/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-mdpi-v11/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-mdpi/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi-v11/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xhdpi-v11/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xhdpi/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi-v11/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi-v11/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_heart.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_home.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_palm_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_palm_tree.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_reset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_reset.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_stat_action_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxhdpi/ic_stat_action_room.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_maps.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
13 |
24 |
25 |
34 |
35 |
44 |
45 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #AAFFFFFF
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/google_maps_api.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | REPLACE
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Geofence Example
5 | TOUCH THE MAP TO SET YOUR MOCK LOCATION
6 | Home Button
7 | Happy Place Button
8 | Reset Map Button
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.0.1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billmote/GeofenceExample/e465af76935e34b9ae1c427435abee5fa508b981/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Feb 11 11:56:17 EST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------