如何在Android中使用语音搜索功能实现自定义搜索视图



我已经使用带有图标的线性布局创建了自定义搜索视图并编辑文本,因此当用户在deDittext上敲击用户时,我会处理这种情况。但是,当用户专注于EditText时,我也需要实现语音搜索。我看到了有关搜索视图的示例,但是所有这些示例都是关于内置工具栏搜索视图(使用菜单项)。是否可以在不使用标准Android搜索视图的情况下实现语音搜索?

尝试使用没有工具栏的搜索视图时,我无法显示麦克风。如果没有工具栏/操作栏,我找不到有关如何使用搜索视图的任何内容。我最终在工具栏上添加了一个额外的麦克风imageButton。这是一些示例代码来处理麦克风:

public class Main5Activity extends AppCompatActivity {
    private static final int REQUEST_CODE = 1234;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        ImageButton speakButton = findViewById(R.id.ib_speak);
        // Disable button if no recognition service is present
        PackageManager pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(
                new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
        if (activities.size() == 0)
        {
            speakButton.setEnabled(false);
            Toast.makeText(getApplicationContext(), "Recognizer not present", Toast.LENGTH_SHORT).show();
        }
    }
    public void speakButtonClicked(View v)
    {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Voice recognition Demo...");
        startActivityForResult(intent, REQUEST_CODE);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
            // Populate the wordsList with the String values the recognition engine thought it heard
            ArrayList<String> matches = data.getStringArrayListExtra(
                    RecognizerIntent.EXTRA_RESULTS);
            if (matches != null) {
                if (matches.size() > 0) {
                    mSearchView.setQuery(matches.get(0), false);
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

此代码可以帮助您使用语音搜索创建自定义搜索视图,在清单文件中添加可搜索的元数据,并添加search.xml。

searchActivity.java

import android.app.SearchManager;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.SearchRecentSuggestions;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class SearchableActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
    ListView mLVCountries;
    SimpleCursorAdapter mCursorAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_searchable);
        // Getting reference to Country List
        mLVCountries = (ListView)findViewById(R.id.lv_countries);       
        // Setting item click listener      
        mLVCountries.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent countryIntent = new Intent(getApplicationContext(), CountryActivity.class);
                // Creating a uri to fetch country details corresponding to selected listview item
                Uri data = Uri.withAppendedPath(CountryContentProvider.CONTENT_URI, String.valueOf(id));
                // Setting uri to the data on the intent
                countryIntent.setData(data);
                // Open the activity
                startActivity(countryIntent);
            }
        });
        // Defining CursorAdapter for the ListView      
        mCursorAdapter = new SimpleCursorAdapter(getBaseContext(),
                android.R.layout.simple_list_item_1,
                null,
                new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1},
                new int[] { android.R.id.text1}, 0);
        // Setting the cursor adapter for the country listview
        mLVCountries.setAdapter(mCursorAdapter);
        // Getting the intent that invoked this activity
        Intent intent = getIntent();        
        // If this activity is invoked by selecting an item from Suggestion of Search dialog or 
        // from listview of SearchActivity
        if(intent.getAction().equals(Intent.ACTION_VIEW)){ 
            Intent countryIntent = new Intent(this, CountryActivity.class);
            countryIntent.setData(intent.getData());
            startActivity(countryIntent);
            finish();           
        }else if(intent.getAction().equals(Intent.ACTION_SEARCH)){ // If this activity is invoked, when user presses "Go" in the Keyboard of Search Dialog
            String query = intent.getStringExtra(SearchManager.QUERY);
            doSearch(query);
        }       
    }   
    private void doSearch(String query){
        Bundle data = new Bundle();
        data.putString("query", query);
        // Invoking onCreateLoader() in non-ui thread
        getSupportLoaderManager().initLoader(1, data, this);        
    }

    /** This method is invoked by initLoader() */
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle data) {
        Uri uri = CountryContentProvider.CONTENT_URI;       
        return new CursorLoader(getBaseContext(), uri, null, null , new String[]{data.getString("query")}, null);   
    }
    /** This method is executed in ui thread, after onCreateLoader() */
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor c) { 
        mCursorAdapter.swapCursor(c);       
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        // TODO Auto-generated method stub      
    }       
}

countrydb.java

import java.util.HashMap;
import android.app.SearchManager;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
public class CountryDB{
    private static final String DBNAME = "country";
    private static final int VERSION = 1;
    private CountryDBOpenHelper mCountryDBOpenHelper;
    private static final String FIELD_ID = "_id";
    private static final String FIELD_NAME = "name";
    private static final String FIELD_FLAG = "flag";
    private static final String FIELD_CURRENCY = "currency";
    private static final String TABLE_NAME = "countries";
    private HashMap<String, String> mAliasMap;

    public CountryDB(Context context){
        mCountryDBOpenHelper = new CountryDBOpenHelper(context, DBNAME, null, VERSION);
        // This HashMap is used to map table fields to Custom Suggestion fields
        mAliasMap = new HashMap<String, String>();
        // Unique id for the each Suggestions ( Mandatory ) 
        mAliasMap.put("_ID", FIELD_ID + " as " + "_id" );
        // Text for Suggestions ( Mandatory )
        mAliasMap.put(SearchManager.SUGGEST_COLUMN_TEXT_1, FIELD_NAME + " as " + SearchManager.SUGGEST_COLUMN_TEXT_1);
        // Icon for Suggestions ( Optional ) 
        mAliasMap.put( SearchManager.SUGGEST_COLUMN_ICON_1, FIELD_FLAG + " as " + SearchManager.SUGGEST_COLUMN_ICON_1);
        // This value will be appended to the Intent data on selecting an item from Search result or Suggestions ( Optional )
        mAliasMap.put( SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, FIELD_ID + " as " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID );
    }

    /** Returns Countries  */
    public Cursor getCountries(String[] selectionArgs){     
        String selection = FIELD_NAME + " like ? ";
        if(selectionArgs!=null){
            selectionArgs[0] = "%"+selectionArgs[0] + "%";          
        }               
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setProjectionMap(mAliasMap);
        queryBuilder.setTables(TABLE_NAME);     
        Cursor c = queryBuilder.query(mCountryDBOpenHelper.getReadableDatabase(), 
                                        new String[] { "_ID", 
                                                        SearchManager.SUGGEST_COLUMN_TEXT_1 , 
                                                        SearchManager.SUGGEST_COLUMN_ICON_1 , 
                                                        SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID } ,
                                        selection, 
                                        selectionArgs, 
                                        null, 
                                        null,
                                        FIELD_NAME + " asc ","10"
                                    );              
        return c;
    }
    /** Return Country corresponding to the id */
    public Cursor getCountry(String id){
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();     
        queryBuilder.setTables(TABLE_NAME);     
        Cursor c = queryBuilder.query(mCountryDBOpenHelper.getReadableDatabase(), 
                                        new String[] { "_id", "name", "flag", "currency" } ,
                                        "_id = ?", new String[] { id } , null, null, null ,"1"
                                    );      
        return c;
    }

    class CountryDBOpenHelper extends SQLiteOpenHelper{
        public CountryDBOpenHelper(     Context context, 
                                        String name,
                                        CursorFactory factory, 
                                        int version ) {
            super(context, DBNAME, factory, VERSION);
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
            String sql = "";
            // Defining table structure
            sql = " create table " + TABLE_NAME + "" +
                                            " ( " +
                                                FIELD_ID + " integer primary key autoincrement, " + 
                                                FIELD_NAME + " varchar(100), " +
                                                FIELD_FLAG + "  int, " +
                                                FIELD_CURRENCY + " varchar(100) " + 
                                            " ) " ;
            // Creating table
            db.execSQL(sql);            
            for(int i=0;i<Country.countries.length;i++){
                // Defining insert statement
                sql = "insert into " + TABLE_NAME + " ( " +
                        FIELD_NAME + " , " +
                        FIELD_FLAG + " , " + 
                        FIELD_CURRENCY + " ) " + 
                        " values ( " + 
                        " '" + Country.countries[i] + "' ," +
                        "  " + Country.flags[i] + "  ," +
                        " '" + Country.currency[i] + "' ) ";
                // Inserting values into table
                db.execSQL(sql);                    
            }
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub          
        }       
    }   
}

countryActivity.java

import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.widget.ImageView;
import android.widget.TextView;
public class CountryActivity extends FragmentActivity implements LoaderCallbacks<Cursor>{
    private Uri mUri;
    private ImageView mIvFlag;
    private TextView mTvName;
    private TextView mTvCurrency;
    @Override
    protected void onCreate(Bundle arg0) {      
        super.onCreate(arg0);
        setContentView(R.layout.activity_country);
        Intent intent = getIntent();
        mUri = intent.getData();
        mIvFlag = (ImageView) findViewById(R.id.iv_flag);
        mTvName = (TextView) findViewById(R.id.tv_name);
        mTvCurrency = (TextView) findViewById(R.id.tv_currency);
        // Invokes the method onCreateloader() in non-ui thread
        getSupportLoaderManager().initLoader(0, null, this);
    }
    /** Invoked by initLoader() */
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {       
        return new CursorLoader(getBaseContext(), mUri, null, null , null, null);
    }
    /** Invoked by onCreateLoader(), will be executed in ui-thread */
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
        if(cursor.moveToFirst()){
            mIvFlag.setImageResource(cursor.getInt(cursor.getColumnIndex(cursor.getColumnName(2))));
            mTvName.setText("Country: "+cursor.getString(cursor.getColumnIndex(cursor.getColumnName(1))));          
            mTvCurrency.setText("Currency: "+cursor.getString(cursor.getColumnIndex(cursor.getColumnName(3))));         
        }
    }
    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        // TODO Auto-generated method stub
    }
}

相关内容

  • 没有找到相关文章

最新更新