我一直试图编写一个简单的应用程序,允许我从全局搜索中搜索,但不管我做什么,我似乎无法让我的应用程序显示在全局搜索中?
package com.mridang.messearch;
import java.util.ArrayList;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.CrossProcessCursor;
import android.database.Cursor;
import android.database.CursorWindow;
import android.database.DataSetObserver;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
public class SearchProvider extends ContentProvider {
final static String AUTHORITY = "com.android.mms.SuggestionsProvider";
public SearchProvider() {
super();
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Uri u = Uri.parse(String.format("content://mms-sms/searchSuggest?pattern=%s", selectionArgs[0]));
Cursor c = getContext().getContentResolver().query(u, null, null, null, null);
return new SuggestionsCursor(c, selectionArgs[0]);
}
private class SuggestionsCursor implements CrossProcessCursor {
Cursor curMessages;
int intColumns;
int intCurrent;
ArrayList<Row> mRows = new ArrayList<Row>();
String mQuery;
public SuggestionsCursor(Cursor cursor, String query) {
curMessages = cursor;
mQuery = query;
intColumns = cursor.getColumnCount();
try {
computeRows();
} catch (SQLiteException ex) {
// This can happen if the user enters -n (anything starting with
// -).
// sqlite3/fts3 can't handle it. Google for
// "logic error or missing database fts3"
// for commentary on it.
mRows.clear(); // assume no results
}
}
public int getCount() {
return mRows.size();
}
private class Row {
private String mSnippet;
private int mRowNumber;
public Row(int row, String snippet) {
mSnippet = snippet.trim();
mRowNumber = row;
}
public String getSnippet() {
return mSnippet;
}
}
private void computeRows() {
int snippetColumn = curMessages.getColumnIndex("snippet");
int count = curMessages.getCount();
String previousSnippet = null;
for (int i = 0; i < count; i++) {
curMessages.moveToPosition(i);
String snippet = curMessages.getString(snippetColumn);
if (!TextUtils.equals(previousSnippet, snippet)) {
mRows.add(new Row(i, snippet));
previousSnippet = snippet;
}
}
}
private int[] computeOffsets(String offsetsString) {
String[] vals = offsetsString.split(" ");
int[] retvals = new int[vals.length];
for (int i = retvals.length - 1; i >= 0; i--) {
retvals[i] = Integer.parseInt(vals[i]);
}
return retvals;
}
public void fillWindow(int position, CursorWindow window) {
int count = getCount();
if (position < 0 || position > count + 1) {
return;
}
window.acquireReference();
try {
int oldpos = getPosition();
int pos = position;
window.clear();
window.setStartPosition(position);
int columnNum = getColumnCount();
window.setNumColumns(columnNum);
while (moveToPosition(pos) && window.allocRow()) {
for (int i = 0; i < columnNum; i++) {
String field = getString(i);
if (field != null) {
if (!window.putString(field, pos, i)) {
window.freeLastRow();
break;
}
} else {
if (!window.putNull(pos, i)) {
window.freeLastRow();
break;
}
}
}
++pos;
}
moveToPosition(oldpos);
} catch (IllegalStateException e) {
// simply ignore it
} finally {
window.releaseReference();
}
}
public CursorWindow getWindow() {
return null;
}
public boolean onMove(int oldPosition, int newPosition) {
return ((CrossProcessCursor) curMessages).onMove(oldPosition, newPosition);
}
private String[] mVirtualColumns = new String[] { SearchManager.SUGGEST_COLUMN_INTENT_DATA,
SearchManager.SUGGEST_COLUMN_INTENT_ACTION, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
SearchManager.SUGGEST_COLUMN_TEXT_1, };
// Cursor column offsets for the above virtual columns.
// These columns exist after the natural columns in the
// database cursor. So, for example, the column called
// SUGGEST_COLUMN_TEXT_1 comes 3 after mDatabaseCursor.getColumnCount().
private final int INTENT_DATA_COLUMN = 0;
private final int INTENT_ACTION_COLUMN = 1;
private final int INTENT_EXTRA_DATA_COLUMN = 2;
private final int INTENT_TEXT_COLUMN = 3;
public int getColumnCount() {
return intColumns + mVirtualColumns.length;
}
public int getColumnIndex(String columnName) {
for (int i = 0; i < mVirtualColumns.length; i++) {
if (mVirtualColumns[i].equals(columnName)) {
return intColumns + i;
}
}
return curMessages.getColumnIndex(columnName);
}
public String[] getColumnNames() {
String[] x = curMessages.getColumnNames();
String[] y = new String[x.length + mVirtualColumns.length];
for (int i = 0; i < x.length; i++) {
y[i] = x[i];
}
for (int i = 0; i < mVirtualColumns.length; i++) {
y[x.length + i] = mVirtualColumns[i];
}
return y;
}
public boolean moveToPosition(int intPosition) {
if (intPosition >= 0 && intPosition < mRows.size()) {
intCurrent = intPosition;
curMessages.moveToPosition(mRows.get(intPosition).mRowNumber);
return true;
} else {
return false;
}
}
public boolean move(int offset) {
return moveToPosition(intCurrent + offset);
}
public boolean moveToFirst() {
return moveToPosition(0);
}
public boolean moveToLast() {
return moveToPosition(mRows.size() - 1);
}
public boolean moveToNext() {
return moveToPosition(intCurrent + 1);
}
public boolean moveToPrevious() {
return curMessages.moveToPrevious();
}
public String getString(int column) {
// if we're returning one of the columns in the underlying database
// column
// then do so here
if (column < intColumns) {
return curMessages.getString(column);
}
// otherwise we're returning one of the synthetic columns.
// the constants like INTENT_DATA_COLUMN are offsets relative to
// mColumnCount.
Row row = mRows.get(intCurrent);
switch (column - intColumns) {
case INTENT_DATA_COLUMN:
Uri.Builder b = Uri.parse("content://mms-sms/search").buildUpon();
b = b.appendQueryParameter("pattern", row.getSnippet());
Uri u = b.build();
return u.toString();
case INTENT_ACTION_COLUMN:
return Intent.ACTION_SEARCH;
case INTENT_EXTRA_DATA_COLUMN:
return row.getSnippet();
case INTENT_TEXT_COLUMN:
return row.getSnippet();
default:
return null;
}
}
public void close() {
curMessages.close();
}
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
curMessages.copyStringToBuffer(columnIndex, buffer);
}
public void deactivate() {
curMessages.deactivate();
}
public byte[] getBlob(int columnIndex) {
return null;
}
public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
return 0;
}
public String getColumnName(int columnIndex) {
return null;
}
public double getDouble(int columnIndex) {
return 0;
}
public Bundle getExtras() {
return Bundle.EMPTY;
}
public float getFloat(int columnIndex) {
return curMessages.getFloat(columnIndex);
}
public int getInt(int columnIndex) {
return curMessages.getInt(columnIndex);
}
public long getLong(int columnIndex) {
return curMessages.getLong(columnIndex);
}
public int getPosition() {
return curMessages.getPosition();
}
public short getShort(int columnIndex) {
return 0;
}
public boolean getWantsAllOnMoveCalls() {
return false;
}
public boolean isAfterLast() {
return intCurrent >= mRows.size();
}
public boolean isBeforeFirst() {
return intCurrent < 0;
}
public boolean isClosed() {
return curMessages.isClosed();
}
public boolean isFirst() {
return intCurrent == 0;
}
public boolean isLast() {
return intCurrent == mRows.size() - 1;
}
public int getType(int columnIndex) {
throw new UnsupportedOperationException(); // TODO revisit
}
public boolean isNull(int columnIndex) {
return false; // TODO revisit
}
public void registerContentObserver(ContentObserver observer) {
curMessages.registerContentObserver(observer);
}
public void registerDataSetObserver(DataSetObserver observer) {
curMessages.registerDataSetObserver(observer);
}
public boolean requery() {
return false;
}
public Bundle respond(Bundle extras) {
return curMessages.respond(extras);
}
public void setNotificationUri(ContentResolver cr, Uri uri) {
curMessages.setNotificationUri(cr, uri);
}
public void unregisterContentObserver(ContentObserver observer) {
curMessages.unregisterContentObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
curMessages.unregisterDataSetObserver(observer);
}
}
}
这是我的清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mridang.messearch"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<provider
android:name=".SearchProvider"
android:authorities="com.mridang.messearch.SearchProvider"
android:exported="true"
android:readPermission="android.permission.READ_SMS" >
<path-permission
android:pathPrefix="/search_suggest_query"
android:readPermission="android.permission.GLOBAL_SEARCH" />
<path-permission
android:pathPrefix="/search_suggest_shortcut"
android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>
<activity
android:name=".SettingsActivity"
android:exported="true"
android:label="@string/title_activity_settings" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
</manifest>
这是我的可搜索配置:
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:includeInGlobalSearch="true"
android:label="@string/search_label"
android:searchSettingsDescription="@string/search_setting_description"
android:searchSuggestAuthority="com.mridang.messearch.SearchProvider"
android:searchSuggestIntentAction="android.intent.action.SEARCH"
android:searchSuggestSelection="pattern" />
当我打开Google搜索应用时,我无法看到我的应用列表,我似乎无法找出原因?关于我做错了什么的想法?似乎全球搜索的唯一应用是Google搜索应用。我无法看到内置于Android中的内容,感觉非常奇怪。