如何让我的应用程序显示在全局搜索中?

时间:2014-09-03 14:19:43

标签: java android android-search

我一直试图编写一个简单的应用程序,允许我从全局搜索中搜索,但不管我做什么,我似乎无法让我的应用程序显示在全局搜索中?

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" />

当我打开Goog​​le搜索应用时,我无法看到我的应用列表,我似乎无法找出原因?关于我做错了什么的想法?似乎全球搜索的唯一应用是Google搜索应用。我无法看到内置于Android中的内容,感觉非常奇怪。

enter image description here

0 个答案:

没有答案