Add Autocomplete SearchView in Open Event Android App

The Open Event Android App has a map for showing all locations of sessions. All the locations have a marker in the map. It is difficult to find a particular location on the map because to know the name of location user has to click on the marker. Adding autocomplete SearchView will improve user experience by providing an ability to search the location by name and by suggesting name according to the search query. In this post I explain how to add autocomplete SearchView in the fragment or activity. Add search icon in actionbar The first step to do is to create a menu xml file and add a search menu item in it. Then inflate this menu xml file in Fragment in onCreateOptionsMenu() method. 1. Create menu.xml file In this file add search menu element. Inside menu element add search menu item. Define id, title, and icon of search menu item. Add android.support.v7.widget.SearchView” as actionViewClass which will be used as action view when the user clicks on the icon. <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <item android:id="@+id/action_search" android:icon="@drawable/ic_search_white_24dp" android:title="@string/search" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="ifRoom | collapseActionView"/> </menu> 2. Inflate menu.xml file in Fragment In the fragment’s onCreateOptionsMenu() method inflate menu.xml file using MenuInflater’s inflate() method. Then find search menu item using menu’s findItem() method by passing id of search menu item as parameter. public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_map, menu); MenuItem item = menu.findItem(R.id.action_search); } Add and initialize SearchView   Now after adding search icon we need to add SearchView and SearchAutoComplete fields in the fragment. private SearchView searchView; private SearchView.SearchAutoComplete mSearchAutoComplete; Initialize SearchView in onCreateOptionMenu() method by passing search menu item in the getActionView() method of MenuItemCompat. Here SearchAutoComplete is a child object of SearchView so initialize it using findViewById method of SearchView by passing the id as parameter. searchView = (SearchView) MenuItemCompat.getActionView(item); mSearchAutoComplete = (SearchView.SearchAutoComplete) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text); Define properties of SearchAutoCompleteView By default background of drop down menu in SearchAutoComplete is black. You can change background using setDropDownBackgroundResource() method. Here i’m making it white by providing white drawable resource. mSearchAutoComplete.setDropDownBackgroundResource(R.drawable.background_white); mSearchAutoComplete.setDropDownAnchor(R.id.action_search); mSearchAutoComplete.setThreshold(0) The setDropDownAnchor() method sets the view to which the auto-complete drop down list should anchor. The setThreshold() method specifies the minimum number of characters the user has to type in the edit box before the drop down list is shown. Create array adapter Now it’s time to make the ArrayAdapter object which will provide the data set (strings) which will be used to run search queries. ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, searchItems); Here searchItems is List of strings. Now set this adapter to the mSearchAutoComplete object using setAdapter() method. mSearchAutoComplete.setAdapter(adapter); Now we are all set to run the app on device or emulator. Here’s demo how it will look Conclusion The SearchView with an ability to give suggestions serves the great user experience in the application. Additional resources: SearchView : https://developer.android.com/reference/android/support/v7/widget/SearchView.html AutoCompleteTextView Tutorial : https://www.tutorialspoint.com/android/android_auto_complete.htm Open Event Android PR : https://github.com/fossasia/open-event-android/pull/1749

Continue ReadingAdd Autocomplete SearchView in Open Event Android App

Save Server Response to File Using Python in Open Event Android App Generator

The Open Event Android project helps event organizers to generate Apps (apk format) using Open Event App generator for their events/conferences by providing API endpoint or zip generated using Open Event server. The Open Event Android project has an assets folder which contains sample JSON files for the event, which are used to load the data when there is no Internet connection. When an organizer generates an app with the help of an API endpoint, then all the assets, e.g. images, are removed and because of it generated don’t have sample JSON files. So if the device is offline then it will not load the data from the assets (issue #1606). The app should contain sample event JSON files and should be able to load the data without the Internet connection. One solution to this problem is to fetch all the event data (JSON files) from the server and save it to the assets folder while generating the app using Open Event App generator. So in this blog post, I explain how to make a simple request using Python and save the response in a file. Making a simple request To fetch the data we need to make a request to the server and the server will return the response for that request. Here’s step to make a simple request, Import Requests module using, import requests The requests module has get, post, put, delete, head, options to make a request. Example: requests.get(self.api_link + '/' + end_point) Here all method returns requests.Response object. We can get all the information we need from this object. So we can make response object like this, response = requests.get(self.api_link + '/' + end_point) Saving response in a file For saving response in a file we need to open/create a file for writing. Create or open file The open() method is used for opening file. It takes two arguments one is file name and second in access mode which determines the mode in which the file has to be opened, i.e., read, write, append, etc. file = open(path/to/the/file, "w+") Here "w+" overwrites the existing file if the file exists. If the file does not exist, it creates a new file for reading and writing. Write and close file Now write the content of the response using the write() method of file object then close the file object using the close()  method. The close() method flushes any unwritten information and closes the file object. file.write(response.text) file.close() Here response.text gives the content of the response in Unicode format. Conclusion The requests.Response object contains much more data like encoding, status_code, headers etc. For more info about request and response refer additional resources given below. Additional Resources Request: http://docs.python-requests.org/en/master/api/ Response: http://docs.python-requests.org/en/master/api/#requests.Response Open Event Android PR: https://github.com/fossasia/open-event-android/pull/1608/files

Continue ReadingSave Server Response to File Using Python in Open Event Android App Generator

JSON Deserialization Using Jackson in Open Event Android App

The Open Event project uses JSON format for transferring event information like tracks, sessions, microlocations and other. The event exported in the zip format from the Open Event server also contains the data in JSON format. The Open Event Android application uses this JSON data. Before we use this data in the app, we have to parse the data to get Java objects that can be used for populating views. Deserialization is the process of converting JSON data to Java objects. In this post I explain how to deserialize JSON data using Jackson. 1. Add dependency In order to use Jackson in your app add following dependencies in your app module’s build.gradle file. dependencies { compile 'com.fasterxml.jackson.core:jackson-core:2.8.9' compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.9' compile 'com.fasterxml.jackson.core:jackson-databind:2.8.9' } 2.  Define entity model of data In the Open Event Android we have so many models like event, session, track, microlocation, speaker etc. Here i am only defining track model because of it’s simplicity and less complexity. public class Track { private int id; private String name; private String description; private String color; @JsonProperty("font-color") private String fontColor; //getters and setters } Here if the property name is same as json attribute key then no need to add JsonProperty annotation like we have done for id, name color property. But if property name is different from json attribute key then it is necessary to add JsonProperty annotation. 3.  Create sample JSON data Let’s create sample JSON format data we want to deserialize. { "id": 273, "name": "Android", "description": "Sample track", "color": "#94868c", "font-color": "#000000" } 4.  Deserialize using ObjectMapper ObjectMapper is Jackson serializer/deserializer. ObjectMapper’s readValue() method is used for simple deserialization. It takes two parameters one is JSON data we want to deserialize and second is Model entity class. Create an ObjectMapper object and initialize it. ObjectMapper objectMapper = new ObjectMapper(); Now create a Model entity object and initialize it with deserialized data from ObjectMapper’s readValue() method. Track track = objectMapper.readValue(json, Track.class); So we have converted JSON data into the Java object. Jackson is very powerful library for JSON serialization and deserialization. To learn more about Jackson features follow the links given below. Jackson-databind: https://github.com/FasterXML/jackson-databind Jackson wiki: http://wiki.fasterxml.com/JacksonInFiveMinutes Tutorial: http://tutorials.jenkov.com/java-json/jackson-installation.html

Continue ReadingJSON Deserialization Using Jackson in Open Event Android App

Cache Thumbnails and Images Using Picasso in Open Event Android

In the event based Android projects like Open Event Android, we have speakers and sponsors. And these projects needs to display image of the speakers and sponsors because it affects project a lot. So instead of every time fetching image from the server it is good to store small images(thumbnails) in the cache and load images even if device is offline. It also reduces data usage. Picasso is mostly used image loading library for Android. It automatically handles ImageView recycling and download cancellation in an adapter, complex image transformations with minimal memory use, memory and disk caching. But one problem is Picasso caches images for only one session by default. I mean if you close the app then all by default cached image will be removed.  If you are offline then Picasso will not load cached images because of it. It will make network calls every time you open the app. In this post I explain how to manually cache images using Picasso so that images load even if the device is offline. It will make a network call only once for a particular image and will cache image in memory. We will use okhttp3 library for OkHttpClient. 1. Add dependency In order to use Picasso in your app add following dependencies in your app module’s build.gradle file. dependencies { compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com.squareup.picasso:picasso:2.5.2' } 2. Make static Picasso object Make static Picasso object in the Application class so that we can use it directly from the other activity. public static Picasso picassoWithCache; 3. Initialize cache Create a File object with path as app specific cache and use this object to create a Cache object. File httpCacheDirectory = new File(getCacheDir(), "picasso-cache"); Cache cache = new Cache(httpCacheDirectory, 15 * 1024 * 1024); Here it will create a Cache object with 15MB. getCacheDir() method returns the absolute path to the application specific cache directory on the filesystem. OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder().cache(cache); 4. Initialize Picasso with cache Now initialize picassoWithCache object using Picass.Builder(). Set downloader for picasso by adding  new OkHttp3Downloader object. picassoWithCache = new Picasso.Builder(this).downloader(new OkHttp3Downloader(okHttpClientBuilder.build())).build(); 5. Use picassoWithCache object As it is a static object you can directly use it from any activity. All the images loaded using this picassoWithCache instance will be cached in memory. Application.picassoWithCache().load(thumbnail/image url);   To know more how i solved this issue in Open Event Project visit this link. To learn more about Picasso features follow the links given below. Documentation : http://square.github.io/picasso/2.x/picasso/ Tutorials : https://futurestud.io/tutorials/picasso-influencing-image-caching

Continue ReadingCache Thumbnails and Images Using Picasso in Open Event Android

How to add Markers in Map Fragment of Open Event Android App

The Open Event Android project helps event organizers to generate Apps (apk format) for their events/conferences by providing API endpoint or zip generated using Open Event server. In the  Open Event Android App, we have a map for showing all locations of sessions. In this map users should be able to see different locations with multiple markers. In this post I explain how to add multiple markers in the Google map fragment and set the bound in the map so that all markers are visible on one screen with specified padding. Create Map Fragment The first step to do is to create a simple xml file and add a fragment element in it. Then create MapsFragment.java file and find fragment element added in the xml file using findFragmentById() method. SupportMapFragment supportMapFragment = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)); 1. Create fragment_map.xml file In this file add FrameLayout as a top level element and add fragment element inside FrameLayout with the name “com.google.android.gms.maps.SupportMapFragment”. <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> 2. Create MapsFragment.java MapsFragment.java extends SupportMapFragement and implements LocationListener, OnMapReadyCallback. Make instance of GoogleMap object. In onViewCreated method inflate fragment_map.xml file using inflater. Now find the fragment element added in the xml file using findFragmentById() method and assign it to SupportMapFragement instance. public class MapsFragment extends SupportMapFragment implements LocationListener, OnMapReadyCallback { private GoogleMap mMap; @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_map, container, false); SupportMapFragment supportMapFragment = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)); supportMapFragment.getMapAsync(this); return view; } @Override public void onMapReady(GoogleMap map) { … } ... } Create list of locations Location object has three variables name, latitude & longitude. Create a list of locations for which we want to add markers to the map. public class Location { private String name; private float latitude; private float longitude; } List<Microlocation> mLocations= new ArrayList<>();   Add location objects in mLocations in onViewCreated() method mLocations.add(location);   You can add multiple locations using for loop or fetching from the database. Add markers Add following code in onMapReady(GoogleMap map) method. onMapReady(GoogleMap map) is called when map is ready to be used. setMapToolbarEnabled(true) used to show toolbar for marker. If the toolbar is enabled users will see a bar with various context-dependent actions, including 'open this map in the Google Maps app' and 'find directions to the highlighted marker in the Google Maps app'. if(map != null){ mMap = map; mMap.getUiSettings().setMapToolbarEnabled(true); } showEventLocationOnMap();   Create showEventLocationOnMap() method and add following code private void showLocationsOnMap(){ float latitude; float longitude; Marker marker; //Add markers for all locations for (Location location : mLocations) { latitude = location.getLatitude(); longitude = location.getLongitude(); latlang = new LatLng(latitude, longitude); marker = mMap.addMarker(new MarkerOptions() .position(latlang) .title(location.getName())); } }   So what we are doing here? For each location object in mLocations list, we are creating LatLng(latitude, longitude)  object and adding it to the map using marker = mMap.addMarker(new MarkerOptions().position(latlang).title(location.getName())); Setting bound We want to set the zoom level so that all markers are visible. To do this, we can…

Continue ReadingHow to add Markers in Map Fragment of Open Event Android App

Debugging Using Stetho in Open Event Android

The Open Event Android project helps event organizers to generator Apps (apk format) for their events/conferences by providing api end point or zip generated using Open Event server. In this android app data is fetched from the internet using network calls to the Open Event server and the data of the event is stored in a database. It is difficult to debug an app with so many network calls and database connectivity. A way to approach this is using  Stetho which is very helpful tool for debugging an app which deals with network calls and database.   Stetho is Facebook’s open source project works as debug bridge for android applications which gives powerful Chrome Developers Tools for debugging android applications using Chrome desktop browser. What can you do using stetho ? Analyze network traffic Inspect elements(layouts/views)   View SQLite database in table format Run queries on SQLite database View shared preference and edit it Manipulate android app from command line Setup 1. Add Gradle dependency To add stetho in your app add ‘com.facebook.stetho:stetho:1.5.0’ dependency in your app  module’s build.gradle file. This dependency is strictly required. dependencies{ compile 'com.facebook.stetho:stetho:1.5.0' } For network inspection add one of the following dependency according to which you will be using 'com.facebook.stetho:stetho-okhttp:1.5.0' 'com.facebook.stetho:stetho-okhttp3:1.5.0' 'com.facebook.stetho:stetho-urlconnection:1.5.0' 2. Initialize stetho Initialize stetho in class MyApplication which extends Application class by overriding  onCreate() method. Make sure you have added MyAppication in manifest. public class MyApplication extends Application { public void onCreate() { super.onCreate() Stetho.initializeWithDefaults(this); } } Stetho.initializeWithDefaults(this) initializes stetho with defaults configuration(without network inspection and more). It will be able to debug database. Manifest file <Application   android:name=”.MyApplication”    …   /> For enabling network inspection add StethoInterceptor  in OkHttpClient new OkHttpClient.Builder()    .addNetworkInterceptor(new StethoInterceptor())    .build(); Using Chrome Developer Tools 1. Open Inspect window Run stetho initialized app on device or emulator then start Google chrome and type chrome://inspect. You will see you device with your app’s package name. Click on “inspect”2. Network Inspection Go to Network tab. It will show all network calls. With almost all info like url(path), method, returned status code, returned data type, size, time taken etc. You can also see preview of image and preview, response of returned json data by clicking on Name. 3. SQLite Database Go to “Resources”  tab and select “Web SQL”. You will see database file(.db). By clicking on database file you will see all tables in that database file. And by clicking on table name you will see data in row-column format for that table. 4. Run queries on SQLite database Same as above go to “Resources”  tab and select “Web SQL”. You will see database file(.db). By clicking on database file you will see console on right side, where you can run queries on SQLite database. Example, SELECT * FROM tracks ; 5. Shared Preferences Inspection Go to “Resources”  tab and select “Local Storage”. You will show all files that your app used to save key-value pairs in shared preference and by clicking on file you will see all key-value pairs. 6. Element(View/Layout) Inspection…

Continue ReadingDebugging Using Stetho in Open Event Android