Android SearchView Widget with ActionBarCompat library

In this article we will develop an Android application that demonstrates how to create a searchview widget in action bar using ActionBarCompat library.

This application facilitates users to search places using Google Places API. As user types in place name in searchview, places that matches the typed in characters will be listed as suggestions. On selecting an item from the suggestion, the corresponding place will be shown in the Google Maps Android API V2.

We need following for this application :

ActionBarCompat library : We know that, SearchView widget is only available since Android API Level 11 and its previous versions does not have the SearchView widget. In order for the backward compatibility, we can use ActionBarCompat library which is available with Android Support library revision 18.

Google Play Services Library : Since we are using Google Maps Android API V2 with this application, we need Google Play Service library for this application to work.

Configuration file for SearchView widget : This configuration file is used to configure the searchview widget. For this application, this file is available at res/xml/searchable.xml

Searchable Activity : An activity that handles the search requests from searchview widget. In this application, MainActivity acts as the searchable activity.

Content Provider : The searchview widget performs the search operation on the data provided by the content provider.

Loaders : Loaders are used to execute tasks in background ( non-ui thread ) . We are using two loaders in the MainActivity class. One loader is used in the method doSearch() which is invoked when user presses the “Go” button of the soft keyboard. The second loader is used in the method “getPlace()”, which is invoked when an item in the search suggestion list is selected.

Activity Style : The activity that implements the action bar should apply the style Theme.AppCompat or Theme.AppCompat.Light  or Theme.AppCompat.DarkActionBar. This can be done in AndroidManifest.xml file.

This application is developed in Eclipse 4.2.0 with ADT plugin 22.0.5, Android Support library 18 and Google Play Service library 9.

Please jump to end of this article to see the screenshots of this application.


1. Create new Android application project namely “LocationActionBarCompatSearchViewV2″

Create new Android application project

Figure 1 : Create new Android application project


2. Configure the application

Configure the application project

Figure 2 : Configure the application project


3. Design application launcher icon

Design application launcher icon

Figure 3 : Design application launcher icon


4. Create a blank activity

Create a blank activity

Figure 4 : Create a blank activity


5. Enter MainActivity details

Enter MainActivity Details

Figure 5 : Enter MainActivity Details


 6. Setup ActionBarCompat library in Eclipse IDE

Please refer the article titled “Android – Setting up ActionBarCompat support library in Eclipse


7. Download and configure Google Play Services Library in Eclipse

Please follow the given below link to setup Google Play Service library in Eclipse.

http://developer.android.com/google/play-services/setup.html


8. Link this project to ActionBarCompat library and Google Play Service llibrary

Linking this application with Google Play Services library and Action Bar Compat library

Figure 6 : Linking this application with Google Play Services library and Action Bar Compat library


9. Get the API key for Google Maps Android API V2

We need to get an API key from Google to use Google Maps in Android application.

Please follow the given below link to get the API key for Google Maps Android API v2.

https://developers.google.com/maps/documentation/android/start


10. Get the API key for Google Places API

We can create API key for Google Place API by clicking “Create new Browser key”  available at the “API Access” pane of the Google console URL : http://code.google.com/apis/console.

Also ensure that, “Places API” is enabled in the “Services” pane of the Google console.


11. Update the file res/values/strings.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">SearchViewWithActionBarCompat</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_search">Search</string>
    <string name="search_hint">Search Places</string>
    <string name="search_settings">Search Places</string>
</resources>

12. Update the layout file res/layout/activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <fragment
        android:id="@+id/map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

13. Update the menu file res/menu/main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    <item
        android:id="@+id/action_search"
        android:orderInCategory="100"
        android:title="@string/action_search"
        myapp:actionViewClass="android.support.v7.widget.SearchView"
        myapp:showAsAction="always" />
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/action_settings"/>
</menu>

14. Create the class file src/in/wptrafficanalyzer/locationactionbarcompatsearchviewv2/PlaceJSONParser.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package in.wptrafficanalyzer.locationactionbarcompatsearchviewv2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class PlaceJSONParser {
    /** Receives a JSONObject and returns a list */
    public List<HashMap<String,String>> parse(JSONObject jObject){
        JSONArray jPlaces = null;
        try {
            /** Retrieves all the elements in the 'places' array */
            jPlaces = jObject.getJSONArray("predictions");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        /** Invoking getPlaces with the array of json object
        * where each json object represent a place
        */
        return getPlaces(jPlaces);
    }
    private List<HashMap<String, String>> getPlaces(JSONArray jPlaces){
        int placesCount = jPlaces.length();
        List<HashMap<String, String>> placesList = new ArrayList<HashMap<String,String>>();
        HashMap<String, String> place = null;
        /** Taking each place, parses and adds to list object */
        for(int i=0; i<placesCount;i++){
            try {
                /** Call getPlace with place JSON object to parse the place */
                place = getPlace((JSONObject)jPlaces.get(i));
                placesList.add(place);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return placesList;
    }
    /** Parsing the Place JSON object */
    private HashMap<String, String> getPlace(JSONObject jPlace){
        HashMap<String, String> place = new HashMap<String, String>();
        String id="";
        String reference="";
        String description="";
        try {
            description = jPlace.getString("description");
            id = jPlace.getString("id");
            reference = jPlace.getString("reference");
            place.put("description", description);
            place.put("_id",id);
            place.put("reference",reference);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return place;
    }
}

15. Create the class file src/in/wptrafficanalyzer/locationactionbarcompatsearchviewv2/PlaceDetailsJSONParser.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package in.wptrafficanalyzer.locationactionbarcompatsearchviewv2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
public class PlaceDetailsJSONParser {
    /** Receives a JSONObject and returns a list */
    public List<HashMap<String,String>> parse(JSONObject jObject){
        Double lat = Double.valueOf(0);
        Double lng = Double.valueOf(0);
        String formattedAddress = "";
        HashMap<String, String> hm = new HashMap<String, String>();
        List<HashMap<String, String>> list = new ArrayList<HashMap<String,String>>();
        try {
            lat = (Double)jObject.getJSONObject("result").getJSONObject("geometry").getJSONObject("location").get("lat");
            lng = (Double)jObject.getJSONObject("result").getJSONObject("geometry").getJSONObject("location").get("lng");
            formattedAddress = (String) jObject.getJSONObject("result").get("formatted_address");
        } catch (JSONException e) {
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        hm.put("lat", Double.toString(lat));
        hm.put("lng", Double.toString(lng));
        hm.put("formatted_address",formattedAddress);
        list.add(hm);
        return list;
    }
}

16. Create the file src/in/wptrafficanalyzer/locationactionbarcompatsearchviewv2/PlaceProvider.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
package in.wptrafficanalyzer.locationactionbarcompatsearchviewv2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.util.Log;
public class PlaceProvider extends ContentProvider {
    public static final String AUTHORITY = "in.wptrafficanalyzer.locationsherlocksearchviewmapv2.PlaceProvider";
    public static final Uri SEARCH_URI = Uri.parse("content://"+AUTHORITY+"/search");
    public static final Uri DETAILS_URI = Uri.parse("content://"+AUTHORITY+"/details");
    private static final int SEARCH = 1;
    private static final int SUGGESTIONS = 2;
    private static final int DETAILS = 3;
    // Obtain browser key from https://code.google.com/apis/console
    String mKey = "key=YOUR_BROWSER_KEY";
    // Defines a set of uris allowed with this content provider
    private static final UriMatcher mUriMatcher = buildUriMatcher();
    private static UriMatcher buildUriMatcher() {
        UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        // URI for "Go" button
        uriMatcher.addURI(AUTHORITY, "search", SEARCH );
        // URI for suggestions in Search Dialog
        uriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY,SUGGESTIONS);
        // URI for Details
        uriMatcher.addURI(AUTHORITY, "details",DETAILS);
        return uriMatcher;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {
        Cursor c = null;
        PlaceJSONParser parser = new PlaceJSONParser();
        PlaceDetailsJSONParser detailsParser = new PlaceDetailsJSONParser();
        String jsonString = "";
        String jsonPlaceDetails = "";
        List<HashMap<String, String>> list = null;
        List<HashMap<String, String>> detailsList = null;
        MatrixCursor mCursor = null;
        switch(mUriMatcher.match(uri)){
        case SEARCH:
            // Defining a cursor object with columns description, lat and lng
            mCursor = new MatrixCursor(new String[] { "description","lat","lng" });
            // Create a parser object to parse places in JSON format
            parser = new PlaceJSONParser();
            // Create a parser object to parse place details in JSON format
            detailsParser = new PlaceDetailsJSONParser();
            // Get Places from Google Places API
            jsonString = getPlaces(selectionArgs);
            try {
                // Parse the places ( JSON => List )
                list = parser.parse(new JSONObject(jsonString));
                // Finding latitude and longitude for each places using Google Places Details API
                for(int i=0;i<list.size();i++){
                    HashMap<String, String> hMap = (HashMap<String, String>) list.get(i);
                    detailsParser =new PlaceDetailsJSONParser();
                    // Get Place details
                    jsonPlaceDetails = getPlaceDetails(hMap.get("reference"));
                    // Parse the details ( JSON => List )
                    detailsList = detailsParser.parse(new JSONObject(jsonPlaceDetails));
                    // Creating cursor object with places
                    for(int j=0;j<detailsList.size();j++){
                        HashMap<String, String> hMapDetails = detailsList.get(j);
                        // Adding place details to cursor
                        mCursor.addRow(new String[]{ hMap.get("description") , hMapDetails.get("lat") , hMapDetails.get("lng") });
                    }
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            c = mCursor;
            break;
        case SUGGESTIONS :
            // Defining a cursor object with columns id, SUGGEST_COLUMN_TEXT_1, SUGGEST_COLUMN_INTENT_EXTRA_DATA
            mCursor = new MatrixCursor(new String[] { "_id", SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA } );
            // Creating a parser object to parse places in JSON format
            parser = new PlaceJSONParser();
            // Get Places from Google Places API
            jsonString = getPlaces(selectionArgs);
            try {
                // Parse the places ( JSON => List )
                list = parser.parse(new JSONObject(jsonString));
                // Creating cursor object with places
                for(int i=0;i<list.size();i++){
                    HashMap<String, String> hMap = (HashMap<String, String>) list.get(i);
                    // Adding place details to cursor
                    mCursor.addRow(new String[] { Integer.toString(i), hMap.get("description"), hMap.get("reference") });
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            c = mCursor;
            break;
        case DETAILS :
            // Defining a cursor object with columns description, lat and lng
            mCursor = new MatrixCursor(new String[] { "description","lat","lng" });
            detailsParser = new PlaceDetailsJSONParser();
            jsonPlaceDetails = getPlaceDetails(selectionArgs[0]);
            try {
                detailsList = detailsParser.parse(new JSONObject(jsonPlaceDetails));
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            for(int j=0;j<detailsList.size();j++){
                HashMap<String, String> hMapDetails = detailsList.get(j);
                mCursor.addRow(new String[]{ hMapDetails.get("formatted_address") , hMapDetails.get("lat") , hMapDetails.get("lng") });
            }
            c = mCursor;
            break;
        }
        return c;
    }
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }
    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        return false;
    }
    @Override
    public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }
    /** A method to download json data from url */
    private String downloadUrl(String strUrl) throws IOException{
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try{
            URL url = new URL(strUrl);
            // Creating an http connection to communicate with url
            urlConnection = (HttpURLConnection) url.openConnection();
            // Connecting to url
            urlConnection.connect();
            // Reading data from url
            iStream = urlConnection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
            StringBuffer sb = new StringBuffer();
            String line = "";
            while( ( line = br.readLine()) != null){
                sb.append(line);
            }
            data = sb.toString();
            br.close();
        }catch(Exception e){
           Log.d("Exception while downloading url", e.toString());
        }finally{
            iStream.close();
            urlConnection.disconnect();
        }
        return data;
    }
    private String getPlaceDetailsUrl(String ref){
        // reference of place
        String reference = "reference="+ref;
        // Sensor enabled
        String sensor = "sensor=false";
        // Building the parameters to the web service
        String parameters = reference+"&"+sensor+"&"+mKey;
        // Output format
        String output = "json";
        // Building the url to the web service
        String url = "https://maps.googleapis.com/maps/api/place/details/"+output+"?"+parameters;
        return url;
    }
    private String getPlacesUrl(String qry){
        try {
            qry = "input=" + URLEncoder.encode(qry, "utf-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        // Sensor enabled
        String sensor = "sensor=false";
        // place type to be searched
        String types = "types=geocode";
        // Building the parameters to the web service
        String parameters = qry+"&"+types+"&"+sensor+"&"+mKey;
        // Output format
        String output = "json";
        // Building the url to the web service
        String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
        return url;
    }
    private String getPlaces(String[] params){
        // For storing data from web service
        String data = "";
        String url = getPlacesUrl(params[0]);
        try{
            // Fetching the data from web service in background
            data = downloadUrl(url);
        }catch(Exception e){
            Log.d("Background Task",e.toString());
        }
        return data;
    }
    private String getPlaceDetails(String reference){
        String data = "";
        String url = getPlaceDetailsUrl(reference);
        try {
            data = downloadUrl(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
}

Note : Update “YOUR_BROWSER_KEY on line 39 with the browser key obtained in Step 10.


17. Update the class MainActivity in the file src/in/wptrafficanalyzer/locationactionbarcompatsearchviewv2/MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package in.wptrafficanalyzer.locationactionbarcompatsearchviewv2;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
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.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends ActionBarActivity implements LoaderCallbacks<Cursor>{
    GoogleMap mGoogleMap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mGoogleMap = fragment.getMap();
        handleIntent(getIntent());
    }
    private void handleIntent(Intent intent){
        if(intent.getAction().equals(Intent.ACTION_SEARCH)){
            doSearch(intent.getStringExtra(SearchManager.QUERY));
        }else if(intent.getAction().equals(Intent.ACTION_VIEW)){
            getPlace(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
        }
    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        handleIntent(intent);
    }
    private void doSearch(String query){
        Bundle data = new Bundle();
        data.putString("query", query);
        getSupportLoaderManager().restartLoader(0, data, this);
    }
    private void getPlace(String query){
        Bundle data = new Bundle();
        data.putString("query", query);
        getSupportLoaderManager().restartLoader(1, data, this);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        // Get the SearchView and set the searchable configuration
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        MenuItem searchItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        // searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        // Assumes current activity is the searchable activity
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        // searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public android.support.v4.content.Loader<Cursor> onCreateLoader(int arg0,
        Bundle query) {
        CursorLoader cLoader = null;
        if(arg0==0)
            cLoader = new CursorLoader(getBaseContext(), PlaceProvider.SEARCH_URI, null, null, new String[]{ query.getString("query") }, null);
        else if(arg0==1)
            cLoader = new CursorLoader(getBaseContext(), PlaceProvider.DETAILS_URI, null, null, new String[]{ query.getString("query") }, null);
        return cLoader;
    }
    @Override
    public void onLoadFinished(android.support.v4.content.Loader<Cursor> arg0,
        Cursor c) {
        showLocations(c);
    }
    @Override
    public void onLoaderReset(android.support.v4.content.Loader<Cursor> arg0) {
        // TODO Auto-generated method stub
    }
    private void showLocations(Cursor c){
        MarkerOptions markerOptions = null;
        LatLng position = null;
        mGoogleMap.clear();
        while(c.moveToNext()){
            markerOptions = new MarkerOptions();
            position = new LatLng(Double.parseDouble(c.getString(1)),Double.parseDouble(c.getString(2)));
            markerOptions.position(position);
            markerOptions.title(c.getString(0));
            mGoogleMap.addMarker(markerOptions);
        }
        if(position!=null){
            CameraUpdate cameraPosition = CameraUpdateFactory.newLatLng(position);
            mGoogleMap.animateCamera(cameraPosition);
        }
    }
}

18. Update the configuration file /res/xml/searchable.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/search_hint"
    android:searchSettingsDescription="@string/search_settings"
    android:searchSuggestAuthority="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2.PlaceProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestSelection=" ?"
    android:searchSuggestThreshold="2" >
</searchable>

19. Update the file AndroidManifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="utf-8"?>
    package="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <!-- Protect the map component of the application using application signature -->
    <permission
        android:name="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />
    <!-- Allows to receive map -->
    <uses-permission android:name="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2.permission.MAPS_RECEIVE" />
    <!-- Used by the Google Maps Android API V2 to download map tiles from Google Maps servers -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Allows the Google Maps Android API V2 to cache map tile data in the device's external storage area -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- Allows the Google Maps Android API V2 to use WiFi or mobile cell data (or both) to determine the device's location -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- Allows the Google Maps Android API V2 to use the Global Positioning System (GPS)
    to determine the device's location to within a very small area -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- Allows to contact Google Serves -->
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <!-- Google Maps Android API V2 requires OpenGL ES version 2 -->
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat" >
        <activity
            android:name="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2.MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <!-- Points to searchable activity -->
            <meta-data android:name="android.app.default_searchable"
                android:value=".MainActivity" />
            <!-- Points to searchable meta data -->
            <meta-data android:name="android.app.searchable"
                android:resource="@xml/searchable"/>
        </activity>
        <provider
            android:name=".PlaceProvider"
            android:authorities="in.wptrafficanalyzer.locationactionbarcompatsearchviewv2.PlaceProvider"
            android:exported="false" />
        <!-- Specifies the Android API Key, which is obtained from Google API Console -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="YOUR_ANDROID_API_KEY" />
    </application>
</manifest>

Note : Update “YOUR_ANDROID_API_KEY on line 76 with the Android API key obtained in Step 9.


20. Screenshots of the application

Searching places in SearchView Widget

Figure 7 : Searching places in SearchView Widget


Showing selected place in Google Maps

Figure 8 : Showing selected place in Google Maps


21. Download Source code

Source : http://wptrafficanalyzer.in/blog/android-searchview-widget-with-actionbarcompat-library/
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s