Tuesday, February 26, 2008

Implementing Search

SDK : M5-rc14

We'll implement a Search feature into the image viewing application we built previously. Ideally, this Search should have been implemented using Filter-Search, but due to some bugs in it, we'll be using Query-Search.

AndroidManifest.xml
<activity android:name=".Images" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.default_searchable" android:value=".app.ImageSearch" />
</activity>

- Add the meta-data tag to the Image activity declaration.

- Detail explanation for this and all following tags is available in the documentation. Simply put, whenever a search is launched in this activity, ImageSearch will be the default class to handle the search.



<activity android:name="ImageSearch" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
</activity>


- Add the ImageSearch activity declaration. This activity will receive and handle the search queries.



searchable.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:searchLabel="Images" />

- Add this file to res/xml/ .



Images.java

public boolean onSearchRequested() { startSearch(null, null); return true; }

- This is the only piece of extra code that we'll be adding to the existing Images.java




ImageSearch.java


protected void onCreate(Bundle icicle)
{

super.onCreate(icicle);
final Intent queryIntent = getIntent();
final String queryAction = queryIntent.getAction();
if (Intent.SEARCH_ACTION.equals(queryAction))
{
doSearchQuery(queryIntent, "onCreate()");
}

setContentView(R.layout.searchresult);
GridView g = (GridView) findViewById(R.id.myGrid);
g.setAdapter(new ImageAdapter(ImageSearch.this));
}


- The if construct will check if the intent recieved is SEARCH_ACTION.

- The search results will be shown as a GridView of images.




public void onNewIntent(final Intent newIntent)
{
super.onNewIntent(newIntent);
final Intent queryIntent = getIntent();
final String queryAction = queryIntent.getAction();
if (Intent.SEARCH_ACTION.equals(queryAction))
{
doSearchQuery(queryIntent, "onNewIntent()");
}
}


- Not used. Included only for explanation.

-
This method should be used in two situations,

a. If the search results activity(ImageSearch.java in this case) should also invoke a search.

b. for implementing Filter-Search.




private void doSearchQuery(final Intent queryIntent, final String entryPoint)
{
result = new ArrayList<String>();

queryString = queryString + queryIntent.getStringExtra(SearchManager.QUERY);

setTitle("Search results for "+"'"+queryString+"'");

for(String file : Images.mFiles)
{
if(file.contains(queryString))
{
result.add(file);
}
}

mUris = new Uri[result.size()];

for(int i=0; i < result.size(); i++)
{
mUris[i] = Uri.parse(result.get(i));
}
}



- In this method, we will use the query we received to select the results from the images stored in mFiles array.

- queryString will store the user-query.

- result ArrayList will store paths of all the images that match the query.

- From the result ArrayList, paths will be passed on to the Uri array and then to the ImageAdapter, like in the case of Images.java.


ImageSearch.java consists of some more methods and classes , but they are similar to the View constructed in Images.java, except, there we used Gallery and here we are using GridView.



Source :


Code for Images.java remains the same except for the small method as mentioned above.


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tp.proj">
<application android:icon="@drawable/icon">
<activity android:name=".Images" android:label="@string/app_name" >
<intent-filter>

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.default_searchable"
android:value=".app.ImageSearch" />
</activity>

<!-- Search Activity -->
<activity android:name="ImageSearch"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
</manifest>





res/xml/searchable.xml

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:searchLabel="Images"/>



searchresult.xml (Layout for ImageSearch)

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/myGrid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:verticalSpacing="10"

android:horizontalSpacing="10"
android:numColumns="4"
android:columnWidth="60"
android:stretchMode="columnWidth"

android:gravity="center"
/>



ImageSearch.java

public class ImageSearch extends Activity
{
String queryString = "";
ArrayList<String> result;
String oldQuery=null;
String[] resultarray;
private Uri[] mUris;
protected void onCreate(Bundle icicle)
{

super.onCreate(icicle);
final Intent queryIntent = getIntent();
final String queryAction = queryIntent.getAction();
if (Intent.SEARCH_ACTION.equals(queryAction))
{
doSearchQuery(queryIntent, "onCreate()");
}

setContentView(R.layout.searchresult);
GridView g = (GridView) findViewById(R.id.myGrid);
g.setAdapter(new ImageAdapter(ImageSearch.this));

}

public View makeView()
{
ImageView i = new ImageView(this);
i.setBackgroundColor(0xFF000000);
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
i.setLayoutParams(new LayoutParams(80,80));
return i;
}

@Override
public void onNewIntent(final Intent newIntent)
{
super.onNewIntent(newIntent);

final Intent queryIntent = getIntent();
final String queryAction = queryIntent.getAction();
if (Intent.SEARCH_ACTION.equals(queryAction))
{
doSearchQuery(queryIntent, "onNewIntent()");
}
}

public class ImageAdapter extends BaseAdapter
{

public ImageAdapter(Context c)
{
mContext = c;
}

public int getCount()
{
return mUris.length;
}

public Object getItem(int position)
{
return position;
}

public long getItemId(int position)
{
return position;
}

public View getView(int position, View convertView, ViewGroup parent)
{
ImageView i = new ImageView(mContext);

i.setImageURI(mUris[position]);
i.setLayoutParams(new Gallery.LayoutParams(120, 100));
i.setAdjustViewBounds(false);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setPadding(8, 10, 16, 8);
return i;
}

private Context mContext;

}

private void doSearchQuery(final Intent queryIntent, final String entryPoint)
{
result = new ArrayList<String>();

queryString = queryString + queryIntent.getStringExtra(SearchManager.QUERY);

setTitle("Search results for "+"'"+queryString+"'");

for(String file : Images.mFiles)
{
if(file.contains(queryString))
{
result.add(file);
}
}

mUris = new Uri[result.size()];

for(int i=0; i < result.size(); i++)
{
mUris[i] = Uri.parse(result.get(i));
}

}
}


8 comments:

Unknown said...

Hi GodsMoon, Nice work man.:)
But, Image search is not working to me. Can you attach Full Source code.

Thanks and Regards, :)
Venkat.

Living Sword said...

what is the problem in ImageSearch precisely ? here is the full source. it searches in database.

Unknown said...

HI Living Sword,
Thanks you very much for your reply.
i got your source code. :)
if i have any problem i will let you know. :)

once again , Thank you very much. :)

Unknown said...

Hi living sword,
i inserted some images into sdcards and tested your program , it's working perfectly. when i restart my eclips all the images which i stored in sdcard will be gone. i have to push images once again and have to test.
Can you tell me what is problem.
Thanks :)

Living Sword said...

did that happen only once or does it happen everytime ?

Eshwar said...

Thanks a lot for this great tutorial. The link to download the source code doesn't seem to be working. Can you please post the source code for download again.

Thanks,
Slater

Android app developer said...

I think most of the peoples are likes your blog, because its having the wonderful information about android.

Unknown said...

Accounts Receivable Management Software