Java tutorial
/** * Copyright 2014 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.gms.location.sample.geofencing; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.support.v7.app.ActionBarActivity; import android.telephony.CellLocation; import android.telephony.NeighboringCellInfo; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.location.Geofence; import com.google.android.gms.location.GeofencingRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.GeofencingApi; import com.google.android.gms.location.sample.geofencing.database.DataSource; import com.google.android.gms.location.sample.geofencing.database.DatabaseHelper; import com.google.android.gms.location.sample.geofencing.listener.MyPhoneStateListener; import com.google.android.gms.location.sample.geofencing.model.NetworkDetailModel; import com.google.android.gms.location.sample.geofencing.services.GsmService; import com.google.android.gms.location.sample.geofencing.utils.UtilityMethods; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; /** * Demonstrates how to create and remove geofences using the GeofencingApi. Uses an IntentService * to monitor geofence transitions and creates notifications whenever a device enters or exits * a geofence. * * This sample requires a device's Location settings to be turned on. It also requires * the ACCESS_FINE_LOCATION permission, as specified in AndroidManifest.xml. * * Note that this Activity implements ResultCallback<Status>, requiring that * {@code onResult} must be defined. The {@code onResult} runs when the result of calling * {@link GeofencingApi#addGeofences(GoogleApiClient, GeofencingRequest, PendingIntent)} addGeofences()} or * {@link com.google.android.gms.location.GeofencingApi#removeGeofences(GoogleApiClient, java.util.List)} removeGeofences()} * becomes available. */ public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status>, OnMapReadyCallback, GoogleMap.OnMapClickListener { protected static final String TAG = "MainActivity"; /** * Provides the entry point to Google Play services. */ protected GoogleApiClient mGoogleApiClient; /** * The list of geofences used in this sample. */ protected ArrayList<Geofence> mGeofenceList; /** * Used to keep track of whether geofences were added. */ private boolean mGeofencesAdded; /** * Used when requesting to add or remove geofences. */ private PendingIntent mGeofencePendingIntent; /** * Used to persist application state about whether geofences were added. */ private SharedPreferences mSharedPreferences; // Buttons for kicking off the process of adding or removing geofences. private Button mAddGeofencesButton; private Button mRemoveGeofencesButton; private GoogleMap googleMap; private PlacesAutoCompleteAdapter mAdapter; HandlerThread mHandlerThread; Handler mThreadHandler; private String place = "default"; private DataSource dataSource; private List<NetworkDetailModel> mNetworkDetailModelList; private LatLng mLatLng; @Override public void onMapClick(LatLng latLng) { Marker marker = googleMap.addMarker(new MarkerOptions().position(latLng).draggable(true).title(place)); mGeofenceList.clear(); mGeofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(place) // Set the circular region of this geofence. .setCircularRegion(latLng.latitude, latLng.longitude, Constants.GEOFENCE_RADIUS_IN_METERS) // Set the expiration duration of the geofence. This geofence gets automatically // removed after this period of time. .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these // transition. We track entry and exit transitions in this sample. .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence. .build()); mNetworkDetailModelList = UtilityMethods.getNetworkDetails(this); storeInDb(latLng); } private void storeInDb(LatLng latLng) { String towerIds = Constants.NOT_AVAILABLE; if (mNetworkDetailModelList != null && !mNetworkDetailModelList.isEmpty()) { JSONArray array = new JSONArray(); int size = mNetworkDetailModelList.size(); for (int i = 0; i < size; i++) { JSONObject object = new JSONObject(); NetworkDetailModel model = mNetworkDetailModelList.get(i); try { object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.LAC, model.getLac()); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.TOWER_IDS, model.getCellID()); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.MNC, model.getMnc()); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.MCC, model.getMcc()); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.LAT, latLng.latitude); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.LNG, latLng.longitude); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.OPERATOR_NAME, model.getOperatorName()); object.put(DatabaseHelper.IUserGeoFenceDetails.Columns.RSSI, model.getRssid()); array.put(object); } catch (JSONException ex) { Log.i("Exception", "exception" + ex); } towerIds = array.toString(); } long i = dataSource.insertGeofenceDetails(place, Double.toString(latLng.latitude), Double.toString(latLng.longitude), towerIds, GeoFenceApp.getLocationUtilityInstance().getLocation()); Log.i("tag", "i:" + i); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); startService(new Intent(this, GsmService.class)); MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); GeoFenceApp.getLocationUtilityInstance().initialize(this); dataSource = GeoFenceApp.getInstance().getDataSource(); TelephonyManager tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String networkOperator = tel.getNetworkOperator(); int mcc = 0, mnc = 0; if (networkOperator != null) { mcc = Integer.parseInt(networkOperator.substring(0, 3)); mnc = Integer.parseInt(networkOperator.substring(3)); } Log.i("", "mcc:" + mcc); Log.i("", "mnc:" + mnc); final AutoCompleteTextView autocompleteView = (AutoCompleteTextView) findViewById(R.id.autocomplete); mAdapter = new PlacesAutoCompleteAdapter(this, R.layout.text_adapter); autocompleteView.setAdapter(mAdapter); autocompleteView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // Get data associated with the specified position // in the list (AdapterView) String description = (String) parent.getItemAtPosition(position); place = description; Toast.makeText(MainActivity.this, description, Toast.LENGTH_SHORT).show(); try { Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault()); List<Address> addresses = geocoder.getFromLocationName(description, 1); Address address = addresses.get(0); if (addresses.size() > 0) { autocompleteView.clearFocus(); //inputManager.hideSoftInputFromWindow(autocompleteView.getWindowToken(), 0); LatLng latLng = new LatLng(address.getLatitude(), address.getLongitude()); Location location = new Location("Searched_Location"); location.setLatitude(latLng.latitude); location.setLongitude(latLng.longitude); setupMApIfNeeded(latLng); //setUpMapIfNeeded(location); //searchBar.setVisibility(View.GONE); //searchBtn.setVisibility(View.VISIBLE); } } catch (Exception e) { e.printStackTrace(); } } }); // Get the UI widgets. mAddGeofencesButton = (Button) findViewById(R.id.add_geofences_button); mRemoveGeofencesButton = (Button) findViewById(R.id.remove_geofences_button); // Empty list for storing geofences. mGeofenceList = new ArrayList<Geofence>(); // Initially set the PendingIntent used in addGeofences() and removeGeofences() to null. mGeofencePendingIntent = null; // Retrieve an instance of the SharedPreferences object. mSharedPreferences = getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, MODE_PRIVATE); // Get the value of mGeofencesAdded from SharedPreferences. Set to false as a default. mGeofencesAdded = mSharedPreferences.getBoolean(Constants.GEOFENCES_ADDED_KEY, false); setButtonsEnabledState(); // Get the geofences used. Geofence data is hard coded in this sample. populateGeofenceList(); // Kick off the request to build GoogleApiClient. buildGoogleApiClient(); autocompleteView.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { final String value = s.toString(); // Remove all callbacks and messages mThreadHandler.removeCallbacksAndMessages(null); // Now add a new one mThreadHandler.postDelayed(new Runnable() { @Override public void run() { // Background thread mAdapter.resultList = mAdapter.mPlaceAPI.autocomplete(value); // Footer if (mAdapter.resultList.size() > 0) mAdapter.resultList.add("footer"); // Post to Main Thread mThreadHandler.sendEmptyMessage(1); } }, 500); } @Override public void afterTextChanged(Editable s) { //doAfterTextChanged(); } }); if (mThreadHandler == null) { // Initialize and start the HandlerThread // which is basically a Thread with a Looper // attached (hence a MessageQueue) mHandlerThread = new HandlerThread(TAG, android.os.Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); // Initialize the Handler mThreadHandler = new Handler(mHandlerThread.getLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == 1) { ArrayList<String> results = mAdapter.resultList; if (results != null && results.size() > 0) { runOnUiThread(new Runnable() { @Override public void run() { mAdapter.notifyDataSetChanged(); //stuff that updates ui } }); } else { runOnUiThread(new Runnable() { @Override public void run() { //stuff that updates ui mAdapter.notifyDataSetInvalidated(); } }); } } } }; } GetID(); } @Override public void onDestroy() { super.onDestroy(); // Get rid of our Place API Handlers if (mThreadHandler != null) { mThreadHandler.removeCallbacksAndMessages(null); mHandlerThread.quit(); } } /** * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the LocationServices API. */ protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); } private void setupMApIfNeeded(LatLng latLng) { CameraUpdate center = CameraUpdateFactory.newLatLng(latLng); CameraUpdate zoom = CameraUpdateFactory.zoomTo(15); googleMap.moveCamera(center); googleMap.animateCamera(zoom); } @Override protected void onStart() { super.onStart(); mGoogleApiClient.connect(); } @Override protected void onStop() { super.onStop(); mGoogleApiClient.disconnect(); GeoFenceApp.getLocationUtilityInstance().getmGoogleApiClient().disconnect(); } @Override public void onMapReady(GoogleMap map) { //DO WHATEVER YOU WANT WITH GOOGLEMAP googleMap = map; googleMap.setOnMapClickListener(this); map.setMapType(GoogleMap.MAP_TYPE_HYBRID); map.setMyLocationEnabled(true); //map.setTrafficEnabled(true); //map.setIndoorEnabled(true); map.setBuildingsEnabled(false); map.getUiSettings().setZoomControlsEnabled(true); } /** * Runs when a GoogleApiClient object successfully connects. */ @Override public void onConnected(Bundle connectionHint) { Log.i(TAG, "Connected to GoogleApiClient"); } @Override public void onConnectionFailed(ConnectionResult result) { // Refer to the javadoc for ConnectionResult to see what error codes might be returned in // onConnectionFailed. Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); } @Override public void onConnectionSuspended(int cause) { // The connection to Google Play services was lost for some reason. Log.i(TAG, "Connection suspended"); // onConnected() will be called again automatically when the service reconnects } /** * Builds and returns a GeofencingRequest. Specifies the list of geofences to be monitored. * Also specifies how the geofence notifications are initially triggered. */ private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); // The INITIAL_TRIGGER_ENTER flag indicates that geofencing service should trigger a // GEOFENCE_TRANSITION_ENTER notification when the geofence is added and if the device // is already inside that geofence. builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); // Add the geofences to be monitored by geofencing service. builder.addGeofences(mGeofenceList); // Return a GeofencingRequest. return builder.build(); } /** * Adds geofences, which sets alerts to be notified when the device enters or exits one of the * specified geofences. Handles the success or failure results returned by addGeofences(). */ public void addGeofencesButtonHandler(View view) { GetID(); //MyPhoneStateListener listener = new MyPhoneStateListener(); //GsmCellLocation location = new GsmCellLocation(); //location.setLacAndCid(89, 80); //listener.onCellLocationChanged(location); if (!mGoogleApiClient.isConnected()) { Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show(); return; } try { LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, // The GeofenceRequest object. getGeofencingRequest(), // A pending intent that that is reused when calling removeGeofences(). This // pending intent is used to generate an intent when a matched geofence // transition is observed. getGeofencePendingIntent()).setResultCallback(this); // Result processed in onResult(). } catch (SecurityException securityException) { // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission. logSecurityException(securityException); } } /** * Removes geofences, which stops further notifications when the device enters or exits * previously registered geofences. */ public void removeGeofencesButtonHandler(View view) { if (!mGoogleApiClient.isConnected()) { Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show(); return; } try { // Remove geofences. LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, // This is the same pending intent that was used in addGeofences(). getGeofencePendingIntent()).setResultCallback(this); // Result processed in onResult(). } catch (SecurityException securityException) { // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission. logSecurityException(securityException); } } public void readDb(View v) { startActivity(new Intent(this, ReadDB.class)); } private void logSecurityException(SecurityException securityException) { Log.e(TAG, "Invalid location permission. " + "You need to use ACCESS_FINE_LOCATION with geofences", securityException); } /** * Runs when the result of calling addGeofences() and removeGeofences() becomes available. * Either method can complete successfully or with an error. * * Since this activity implements the {@link ResultCallback} interface, we are required to * define this method. * * @param status The Status returned through a PendingIntent when addGeofences() or * removeGeofences() get called. */ public void onResult(Status status) { if (status.isSuccess()) { // Update state and save in shared preferences. mGeofencesAdded = !mGeofencesAdded; SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded); editor.apply(); // Update the UI. Adding geofences enables the Remove Geofences button, and removing // geofences enables the Add Geofences button. setButtonsEnabledState(); Toast.makeText(this, getString(mGeofencesAdded ? R.string.geofences_added : R.string.geofences_removed), Toast.LENGTH_SHORT).show(); } else { // Get the status code for the error and log it using a user-friendly message. String errorMessage = GeofenceErrorMessages.getErrorString(this, status.getStatusCode()); Log.e(TAG, errorMessage); } } /** * Gets a PendingIntent to send with the request to add or remove Geofences. Location Services * issues the Intent inside this PendingIntent whenever a geofence transition occurs for the * current list of geofences. * * @return A PendingIntent for the IntentService that handles geofence transitions. */ private PendingIntent getGeofencePendingIntent() { // Reuse the PendingIntent if we already have it. if (mGeofencePendingIntent != null) { return mGeofencePendingIntent; } Intent intent = new Intent(this, GeofenceTransitionsIntentService.class); // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling // addGeofences() and removeGeofences(). return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } /** * This sample hard codes geofence data. A real app might dynamically create geofences based on * the user's location. */ public void populateGeofenceList() { for (Map.Entry<String, LatLng> entry : Constants.BAY_AREA_LANDMARKS.entrySet()) { mGeofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.getKey()) // Set the circular region of this geofence. .setCircularRegion(entry.getValue().latitude, entry.getValue().longitude, Constants.GEOFENCE_RADIUS_IN_METERS) // Set the expiration duration of the geofence. This geofence gets automatically // removed after this period of time. .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these // transition. We track entry and exit transitions in this sample. .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence. .build()); } } /** * Ensures that only one button is enabled at any time. The Add Geofences button is enabled * if the user hasn't yet added geofences. The Remove Geofences button is enabled if the * user has added geofences. */ private void setButtonsEnabledState() { if (mGeofencesAdded) { mAddGeofencesButton.setEnabled(false); mRemoveGeofencesButton.setEnabled(true); } else { mAddGeofencesButton.setEnabled(true); mRemoveGeofencesButton.setEnabled(false); } mAddGeofencesButton.setEnabled(true); mRemoveGeofencesButton.setEnabled(true); } public void GetID() { List<NeighboringCellInfo> neighCell = null; TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); neighCell = telManager.getNeighboringCellInfo(); for (int i = 0; i < neighCell.size(); i++) { try { NeighboringCellInfo thisCell = neighCell.get(i); int thisNeighCID = thisCell.getCid(); int thisNeighRSSI = thisCell.getRssi(); Log.i("Info:", " cid:" + thisNeighCID + " - " + thisNeighRSSI); } catch (NumberFormatException e) { e.printStackTrace(); NeighboringCellInfo thisCell = neighCell.get(i); Log.i("exception", neighCell.toString()); } } String networkOperator = telManager.getNetworkOperator(); String mcc = "not avl", mnc = "not avl"; if (networkOperator != null) { mcc = networkOperator.substring(0, 3); mnc = networkOperator.substring(3); } Log.i("", "mcc:" + mcc); Log.i("", "mnc:" + mnc); } }