relevent dictionary provider source code
satya - Friday, October 23, 2009 10:09:45 AM
This source code is a quick reference to the original code that is at google
This source code is a quick reference to the original code that is at google
http://developer.android.com/guide/samples/SearchableDictionary/index.html
satya - Friday, October 23, 2009 10:10:51 AM
All the following code has this prefix
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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.
*/
satya - Friday, October 23, 2009 10:11:22 AM
DictionaryProvider.java
/**
* Provides search suggestions for a list of words and their definitions.
*/
public class DictionaryProvider extends ContentProvider {
public static String AUTHORITY = "dictionary";
private static final int SEARCH_SUGGEST = 0;
private static final int SHORTCUT_REFRESH = 1;
private static final UriMatcher sURIMatcher = buildUriMatcher();
/**
* The columns we'll include in our search suggestions. There are others that could be used
* to further customize the suggestions, see the docs in {@link SearchManager} for the details
* on additional columns that are supported.
*/
private static final String[] COLUMNS = {
"_id", // must include this column
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_TEXT_2,
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
};
/**
* Sets up a uri matcher for search suggestion and shortcut refresh queries.
*/
private static UriMatcher buildUriMatcher() {
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, SHORTCUT_REFRESH);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", SHORTCUT_REFRESH);
return matcher;
}
@Override
public boolean onCreate() {
Resources resources = getContext().getResources();
Dictionary.getInstance().ensureLoaded(resources);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
if (!TextUtils.isEmpty(selection)) {
throw new IllegalArgumentException("selection not allowed for " + uri);
}
if (selectionArgs != null && selectionArgs.length != 0) {
throw new IllegalArgumentException("selectionArgs not allowed for " + uri);
}
if (!TextUtils.isEmpty(sortOrder)) {
throw new IllegalArgumentException("sortOrder not allowed for " + uri);
}
switch (sURIMatcher.match(uri)) {
case SEARCH_SUGGEST:
String query = null;
if (uri.getPathSegments().size() > 1) {
query = uri.getLastPathSegment().toLowerCase();
}
return getSuggestions(query, projection);
case SHORTCUT_REFRESH:
String shortcutId = null;
if (uri.getPathSegments().size() > 1) {
shortcutId = uri.getLastPathSegment();
}
return refreshShortcut(shortcutId, projection);
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
}
private Cursor getSuggestions(String query, String[] projection) {
String processedQuery = query == null ? "" : query.toLowerCase();
List<Dictionary.Word> words = Dictionary.getInstance().getMatches(processedQuery);
MatrixCursor cursor = new MatrixCursor(COLUMNS);
for (Dictionary.Word word : words) {
cursor.addRow(columnValuesOfWord(word));
}
return cursor;
}
private Object[] columnValuesOfWord(Dictionary.Word word) {
return new String[] {
word.word, // _id
word.word, // text1
word.definition, // text2
word.word, // intent_data (included when clicking on item)
};
}
/**
* Note: this is unused as is, but if we included
* {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our results, we
* could expect to receive refresh queries on this uri for the id provided, in which case we
* would return a cursor with a single item representing the refreshed suggestion data.
*/
private Cursor refreshShortcut(String shortcutId, String[] projection) {
return null;
}
/**
* All queries for this provider are for the search suggestion and shortcut refresh mime type.
*/
public String getType(Uri uri) {
switch (sURIMatcher.match(uri)) {
case SEARCH_SUGGEST:
return SearchManager.SUGGEST_MIME_TYPE;
case SHORTCUT_REFRESH:
return SearchManager.SHORTCUT_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
}
public Uri insert(Uri uri, ContentValues values) {
throw new UnsupportedOperationException();
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException();
}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException();
}
}
satya - Friday, October 23, 2009 10:12:15 AM
SearchableDictionary.java
/**
* The main activity for the dictionary. Also displays search results triggered by the search
* dialog.
*/
public class SearchableDictionary extends Activity {
private static final int MENU_SEARCH = 1;
private TextView mTextView;
private ListView mList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.textField);
mList = (ListView) findViewById(R.id.list);
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
// from click on search results
Dictionary.getInstance().ensureLoaded(getResources());
String word = intent.getDataString();
Dictionary.Word theWord = Dictionary.getInstance().getMatches(word).get(0);
launchWord(theWord);
finish();
} else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
mTextView.setText(getString(R.string.search_results, query));
WordAdapter wordAdapter = new WordAdapter(Dictionary.getInstance().getMatches(query));
mList.setAdapter(wordAdapter);
mList.setOnItemClickListener(wordAdapter);
}
Log.d("dict", intent.toString());
if (intent.getExtras() != null) {
Log.d("dict", intent.getExtras().keySet().toString());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
.setIcon(android.R.drawable.ic_search_category_default)
.setAlphabeticShortcut(SearchManager.MENU_KEY);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SEARCH:
onSearchRequested();
return true;
}
return super.onOptionsItemSelected(item);
}
private void launchWord(Dictionary.Word theWord) {
Intent next = new Intent();
next.setClass(this, WordActivity.class);
next.putExtra("word", theWord.word);
next.putExtra("definition", theWord.definition);
startActivity(next);
}
class WordAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
private final List<Dictionary.Word> mWords;
private final LayoutInflater mInflater;
public WordAdapter(List<Dictionary.Word> words) {
mWords = words;
mInflater = (LayoutInflater) SearchableDictionary.this.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return mWords.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
TwoLineListItem view = (convertView != null) ? (TwoLineListItem) convertView :
createView(parent);
bindView(view, mWords.get(position));
return view;
}
private TwoLineListItem createView(ViewGroup parent) {
TwoLineListItem item = (TwoLineListItem) mInflater.inflate(
android.R.layout.simple_list_item_2, parent, false);
item.getText2().setSingleLine();
item.getText2().setEllipsize(TextUtils.TruncateAt.END);
return item;
}
private void bindView(TwoLineListItem view, Dictionary.Word word) {
view.getText1().setText(word.word);
view.getText2().setText(word.definition);
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
launchWord(mWords.get(position));
}
}
}
satya - Friday, October 23, 2009 10:12:56 AM
Dictionary.java
/**
* Contains logic to load the word of words and definitions and find a list of matching words
* given a query. Everything is held in memory; this is not a robust way to serve lots of
* words and is only for demo purposes.
*
* You may want to consider using an SQLite database. In practice, you'll want to make sure your
* suggestion provider is as efficient as possible, as the system will be taxed while performing
* searches across many sources for each keystroke the user enters into Quick Search Box.
*/
public class Dictionary {
public static class Word {
public final String word;
public final String definition;
public Word(String word, String definition) {
this.word = word;
this.definition = definition;
}
}
private static final Dictionary sInstance = new Dictionary();
public static Dictionary getInstance() {
return sInstance;
}
private final Map<String, List<Word>> mDict = new ConcurrentHashMap<String, List<Word>>();
private Dictionary() {
}
private boolean mLoaded = false;
/**
* Loads the words and definitions if they haven't been loaded already.
*
* @param resources Used to load the file containing the words and definitions.
*/
public synchronized void ensureLoaded(final Resources resources) {
if (mLoaded) return;
new Thread(new Runnable() {
public void run() {
try {
loadWords(resources);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private synchronized void loadWords(Resources resources) throws IOException {
if (mLoaded) return;
Log.d("dict", "loading words");
InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line;
while((line = reader.readLine()) != null) {
String[] strings = TextUtils.split(line, "-");
if (strings.length < 2) continue;
addWord(strings[0].trim(), strings[1].trim());
}
} finally {
reader.close();
}
mLoaded = true;
}
public List<Word> getMatches(String query) {
List<Word> list = mDict.get(query);
return list == null ? Collections.EMPTY_LIST : list;
}
private void addWord(String word, String definition) {
final Word theWord = new Word(word, definition);
final int len = word.length();
for (int i = 0; i < len; i++) {
final String prefix = word.substring(0, len - i);
addMatch(prefix, theWord);
}
}
private void addMatch(String query, Word word) {
List<Word> matches = mDict.get(query);
if (matches == null) {
matches = new ArrayList<Word>();
mDict.put(query, matches);
}
matches.add(word);
}
}
satya - Friday, October 23, 2009 10:13:35 AM
WordActivity.java
/**
* Displays a word and its definition.
*/
public class WordActivity extends Activity {
private TextView mWord;
private TextView mDefinition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.word);
mWord = (TextView) findViewById(R.id.word);
mDefinition = (TextView) findViewById(R.id.definition);
Intent intent = getIntent();
String word = intent.getStringExtra("word");
String definition = intent.getStringExtra("definition");
mWord.setText(word);
mDefinition.setText(definition);
}
}
satya - Friday, October 23, 2009 10:14:55 AM
searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search_label"
android:searchSettingsDescription="@string/settings_description"
android:includeInGlobalSearch="true"
android:searchSuggestAuthority="dictionary"
android:searchSuggestIntentAction="android.intent.action.VIEW">
</searchable>