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

时间:2016-11-24 17:08:32

标签: android toolbar searchview

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

2 个答案:

答案 0 :(得分:1)

当我尝试使用没有工具栏的SearchView时,我无法显示麦克风。在没有工具栏/操作栏的情况下,我无法找到有关如何使用SearchView的任何信息。我最终在工具栏上添加了一个额外的麦克风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);
    }
}

答案 1 :(得分:-1)

此代码可以帮助您使用语音搜索创建自定义搜索视图,添加可在清单文件中搜索的元数据,还可以添加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

    }
}