1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 /** 23 * Represents a geographical boundary, also known as a geofence. 24 * 25 * <p>Currently only circular geofences are supported and they do not support altitude changes. 26 * 27 * @hide 28 */ 29 public final class Geofence implements Parcelable { 30 /** @hide */ 31 public static final int TYPE_HORIZONTAL_CIRCLE = 1; 32 33 private final int mType; 34 private final double mLatitude; 35 private final double mLongitude; 36 private final float mRadius; 37 38 /** 39 * Create a circular geofence (on a flat, horizontal plane). 40 * 41 * @param latitude latitude in degrees, between -90 and +90 inclusive 42 * @param longitude longitude in degrees, between -180 and +180 inclusive 43 * @param radius radius in meters 44 * @return a new geofence 45 * @throws IllegalArgumentException if any parameters are out of range 46 */ 47 public static Geofence createCircle(double latitude, double longitude, float radius) { 48 return new Geofence(latitude, longitude, radius); 49 } 50 51 private Geofence(double latitude, double longitude, float radius) { 52 checkRadius(radius); 53 checkLatLong(latitude, longitude); 54 mType = TYPE_HORIZONTAL_CIRCLE; 55 mLatitude = latitude; 56 mLongitude = longitude; 57 mRadius = radius; 58 } 59 60 /** @hide */ 61 public int getType() { 62 return mType; 63 } 64 65 /** @hide */ 66 public double getLatitude() { 67 return mLatitude; 68 } 69 70 /** @hide */ 71 public double getLongitude() { 72 return mLongitude; 73 } 74 75 /** @hide */ 76 public float getRadius() { 77 return mRadius; 78 } 79 80 private static void checkRadius(float radius) { 81 if (radius <= 0) { 82 throw new IllegalArgumentException("invalid radius: " + radius); 83 } 84 } 85 86 private static void checkLatLong(double latitude, double longitude) { 87 if (latitude > 90.0 || latitude < -90.0) { 88 throw new IllegalArgumentException("invalid latitude: " + latitude); 89 } 90 if (longitude > 180.0 || longitude < -180.0) { 91 throw new IllegalArgumentException("invalid longitude: " + longitude); 92 } 93 } 94 95 private static void checkType(int type) { 96 if (type != TYPE_HORIZONTAL_CIRCLE) { 97 throw new IllegalArgumentException("invalid type: " + type); 98 } 99 } 100 101 public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() { 102 @Override 103 public Geofence createFromParcel(Parcel in) { 104 int type = in.readInt(); 105 double latitude = in.readDouble(); 106 double longitude = in.readDouble(); 107 float radius = in.readFloat(); 108 checkType(type); 109 return Geofence.createCircle(latitude, longitude, radius); 110 } 111 @Override 112 public Geofence[] newArray(int size) { 113 return new Geofence[size]; 114 } 115 }; 116 117 @Override 118 public int describeContents() { 119 return 0; 120 } 121 122 @Override 123 public void writeToParcel(Parcel parcel, int flags) { 124 parcel.writeInt(mType); 125 parcel.writeDouble(mLatitude); 126 parcel.writeDouble(mLongitude); 127 parcel.writeFloat(mRadius); 128 } 129 130 private static String typeToString(int type) { 131 switch (type) { 132 case TYPE_HORIZONTAL_CIRCLE: 133 return "CIRCLE"; 134 default: 135 checkType(type); 136 return null; 137 } 138 } 139 140 @Override 141 public String toString() { 142 return String.format("Geofence[%s %.6f, %.6f %.0fm]", 143 typeToString(mType), mLatitude, mLongitude, mRadius); 144 } 145 146 @Override 147 public int hashCode() { 148 final int prime = 31; 149 int result = 1; 150 long temp; 151 temp = Double.doubleToLongBits(mLatitude); 152 result = prime * result + (int) (temp ^ (temp >>> 32)); 153 temp = Double.doubleToLongBits(mLongitude); 154 result = prime * result + (int) (temp ^ (temp >>> 32)); 155 result = prime * result + Float.floatToIntBits(mRadius); 156 result = prime * result + mType; 157 return result; 158 } 159 160 /** 161 * Two geofences are equal if they have identical properties. 162 */ 163 @Override 164 public boolean equals(Object obj) { 165 if (this == obj) 166 return true; 167 if (obj == null) 168 return false; 169 if (!(obj instanceof Geofence)) 170 return false; 171 Geofence other = (Geofence) obj; 172 if (mRadius != other.mRadius) 173 return false; 174 if (mLatitude != other.mLatitude) 175 return false; 176 if (mLongitude != other.mLongitude) 177 return false; 178 if (mType != other.mType) 179 return false; 180 return true; 181 } 182 } 183