SCBG GUIDE ANDROID APP Technical Manual Table of Contents Files Local Garden View & Plant information view Welcome view Mapping Search view GPS Databases Authoring Tool Files Android Studio Project (Ice-cream sandwich) http://people.cs.clemson.edu/~smsouth/files/guidephp o PHP script location http://people.cs.clemson.edu/~smsouth/scbgauthor o Authoring tool location PHP Scripts Add <name> o Inserts a new item of the type in <name> with provided URL arguments AddPlantWithRelation o Used by the authoring tool to add a plant AND make a holder object to match it to a location Get <name> o Returns a json object pertaining to the provided URL ID argument and <name> type GetImageEchoTwo o Returns an image based on the plant ID given (GetImage and GetImageEcho are for note purposes only) Get<Location/Plant>FromID o Returns an item based on provided ID GetLocationWithPlant & GetPlantWithLocation o Uses the holder type to get an array of all the different locations/plants associated with a respective plant/location Local Garden and Local Garden Child views In the project, this view is identified as view number 1. When a user agrees to viewing more information in the map view when entering a certain area, they will be taken to this view. All that this really entails is a listing of all plants associated with a particular location. The plants are gathered in this way from the databasemanager.getPlantsAtLocation(int id) method from the INTERNAL databaseManager. Originally the user is taken to the LocalGarden fragment and all the text fields are simply filled with a default N/A. The Plant listing button will navigate to the LocalGardenChild fragment which is where a subsearch is made. Again, this screen is nearly Identical to the SearchChild but instead of using ALL plants it only uses the plants associated with the lastGarden String array from StaticData (which is set once the user selects to see more information). For details of the search itself, see the description of Search. Map View This is the initial view that the app loads and has the all-important map view. The app had to be registered on googles developer console, just use this key in the android manifest file under the value area for the google services use case. This is for security reasons and as such please don’t use this key for any apps that are not the one it’s associated with. B5:BA:D3:8F:24:5D:3A:82:46:90:64:C6:A4:9A:FF:2B:B6:3C:EB:21;guide.scbg.scbgguide Mapping This map is set to go straight to the main parking lot of the gardens with coordinates (lat to long) 34.67072, 82.824206. Since the map is under a google service it is relatively easy to use once it has been registered through the developer’s console. Something to note here however is that you should not call anything from the map until it has been loaded. This is demonstrated though the map.setOnMapLoadedCallback in the onResume method of the Map fragment. This section is where the locations are loaded from the Internal database and assigned pins depending on their landmark status. Beacons This new feature entails having several Estimote beacons present messages when coming into range. As shown in the database schema there is a table associated with each beacon with the MAC address being the identifier for each one. Estimote does offer an alternative to MAC addresses for identification but that requires each device to be registered on their site. Given the app already uses enough internet it seemed reasonable to simply handle identification independently. Once set up in code the Estimote beacons can be very simple to use effectively. Firstly, an adapter was set up using their API class LeDeviceListAdapter which keeps up with Bluetooth devices. Next is the API BeaconManager (created in the onCreate of the MainActivity). This manager only requires that a ranginglistener be assigned to it that implements the onBeaconsDiscovered method. Inside of this the app runs the rest of the code in a ui thread (to maintain responsiveness), checking each location from the databasemanager with the gathered beacons in range. Note that ONLY estimate beacons are represented here so there is no worry of other devices showing up. After that the manager is started from the onStart method in the mainActivity using connectToService. This method is located at near the end of MainActivity and starts the “ranging” for beacons that come up. Note the stopping and unregistering of the beaconManager in onStop and onDestroy. This prevents the app from using too many resources for no reason when closed or unCached. Search Searching is NOT done via the native dialog as in the iOS version of app. Instead search is done through a child of fragment known as SearchChild. This child has a custom adapter with a text changed listener applied to the main text field. When the text changes ALL plants are filtered through common name, Genus, species, and cultivar. Note that the Latin name printed for each search cell does have a specific ordering to it as a Lain name entails Genus species ‘Culivar’ with species ALWAYS being lowercase and cultivar being in ‘’. When a cell is selected the lastSearch array in StaticData is set which allows the search view to be returned to and still have its data set. This is necessary because search is a fragment and loses its data when transferred via the navigation bar. GPS It would be wise to remember that the ONLY activity in the entire project is the MainActivity, everything else is simply a fragment of it. This results in most all sensor checks to be located in mainActivity like GPS and Beacon support. Remember that GPS is used to detect when a user entered a garden. One option would be to set a proximity trigger using a locationmanager for each of the databases location objects. Based on past experiences trying to make a reliable proximity alarm though API with the iOS version has let to simply checking each location against the users current location via a LocationListener (under listen class located in MainActivity). This approach may be a little slower but given that the location may only do an update every few seconds the delay shouldn’t be noticeable to the user. This listener is assigned in the onResume method of the MainActivity. The external and internal databases are identical with the external being mysql and the internal being sqlite. I recommend using mysql workbench to connect to the external database as opposed to something foreign to it. Host: buffet.cs.clemson.edu Name: SCBGGuide Formal Name: SCBGGuide_jlxd Server: mysql1.cs.clemson.edu Username/Password: Email smsouth@clemson.edu for permission 1 Location: Holds name, description, longitude, latitude, radius, landmark. Landmark is represented as a TinyInt (mysql has no BOOL) and represents if a location is a landmark instead of a normal garden. Holder: This holds a location and plant match, so you can select all plants in location or all locations with plant. (see php files GetFrom* for examples) Plant: Holds name, family, genus, species, cultivar, img, tag, and ebp. Family, genus, species, cultivar are keys matching separate tables (multiple plants can have same of either). Img is a BLOB and is simple used to hold an image representation of the plant. Ebp stands for estimated bloom period and uses locality to match 0 – 11 to the local month representation. Lastmod fields: This isn’t going to be implemented for the initial assignment, but rather globally over the summer session. The purpose of this field to let the apps internal database send it’s date and time with its php calls. These PHP calls will return only those fields that are newer or updated from before. Deleted: These are not currently in the schema but are nun the less planned to be included like the lastmod fields. This will tell if the data field has been deleted or not, if it has then it will be basically ignored by all other functions. Both lastmod and deleted need implementation to stop the app from redownloading all data over again each call. This will require substantial 2 changes to both the iOS and Android apps as well as the Authoring tool, but should be worth the effort in less data transferred. CODE The external database is made through the StaticData class and is activated through multiple calls to network providing the various url locations of the php scripts. These urls can also be found in StaticData and can easily be changed by changing the one primary folder address only. There is no secondary call for when the data is completed but can be set in any fragment creation for syncing with the internal database. The DatabaseManager class deals with this internal database though the use of the built in DatabaseHelper. Note that this database is automatically loaded each time the app starts so there is no need to check for its existence each time. Authoring Tool The authoring tool is located at http://people.cs.clemson.edu/~smsouth/scbgauthor. Index.html is where locations are loaded and displayed with each having an edit/delete/change plants button. Clicking on the single add button above all of them will add in a blank location named “new location”. Plant.html is where change plants will take you too and works in the same manner as location. 3 Clicking edit on either plant or location will use editPlant.html or editLocation.html respectively; the submit button will send the update command to the database. All of the php files used are found at http://people.cs.clemson.edu/~smsouth/files/Guidephp . 4