我甚至不确定谷歌不支持“谷歌即时”这样做是否正确,但我似乎无法找到任何合适的选择。
使用此https://antonioleiva.com/voice_search_google_now/#comment-8611作为指导我正在尝试在我的应用中实施语音搜索,但没有太多运气。
我已经为用户提供了搜索工具。到目前为止我做了什么: -
GlobalApplication.java
public static Queries getQueriesInstance(Context context) {
if(q == null) {
dbHelper = new DbHelper(context);
q = new Queries(db, dbHelper);
}
return q;
}
然后在 MainActivity.java
中@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
Intent i;
int id = item.getItemId();
...
...
if(id == R.id.nav_search) {
i = new Intent(this, SearchActivity.class);
startActivity(i);
}
...
...
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
最后,在添加任何内容之前,我的 SearchActivity.java 文件
package com.projects.activities;
import android.app.SearchManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.SpannableString;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.application.GlobalApplication;
import com.config.Config;
import com.db.Queries;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.libraries.asynctask.MGAsyncTaskNoDialog;
import com.libraries.dataparser.DataParser;
import com.libraries.location.MGLocationManagerUtils;
import com.libraries.utilities.MGUtilities;
import com.models.DataResponse;
import com.models.Deal;
import com.models.DealCategory;
import com.models.Status;
import com.projects.adapp.R;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.util.ArrayList;
public class SearchActivity extends AppCompatActivity implements
GlobalApplication.OnLocationListener{
private AsyncTaskNoDialog task;
SeekBar seekBarRadius;
SwipeRefreshLayout swipeRefresh;
Queries q;
Button btnSearch;
ArrayList<DealCategory> selectedCategories;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
setContentView(R.layout.activity_list_swipe_search);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(R.string.search);
swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
swipeRefresh.setClickable(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
swipeRefresh.setProgressViewOffset(false, 0,100);
}
swipeRefresh.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
showRefresh(false);
q = GlobalApplication.getQueriesInstance(this);
seekBarRadius = (SeekBar) findViewById(R.id.seekBarRadius);
seekBarRadius.setMax(Config.SEARCH_RADIUS_MAX_VALUE);
seekBarRadius.setProgress(Config.SEARCH_RADIUS_DEFAULT_VALUE);
seekBarRadius.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar arg0) { }
@Override
public void onStartTrackingTouch(SeekBar arg0) { }
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
updateRadius(progress);
}
});
updateRadius(seekBarRadius.getProgress());
selectedCategories = new ArrayList<DealCategory>();
btnSearch = (Button) findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
search();
}
});
FrameLayout frameCategory = (FrameLayout) findViewById(R.id.frameCategory);
frameCategory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(SearchActivity.this, CategorySearchActivity.class);
startActivityForResult(i, Config.RESULT_CODE_CATEGORY);
}
});
seekBarRadius.setEnabled(false);
btnSearch.setEnabled(false);
if(!MGUtilities.isLocationEnabled(this) && GlobalApplication.currentLocation == null) {
MGLocationManagerUtils utils = new MGLocationManagerUtils();
utils.setOnAlertListener(new MGLocationManagerUtils.OnAlertListener() {
@Override
public void onPositiveTapped() {
startActivityForResult(
new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS),
Config.PERMISSION_REQUEST_LOCATION_SETTINGS);
}
@Override
public void onNegativeTapped() {
Toast.makeText(SearchActivity.this, R.string.location_error_not_turned_on_search, Toast.LENGTH_LONG).show();
}
});
utils.showAlertView(
this,
R.string.location_error,
R.string.gps_not_on,
R.string.go_to_settings,
R.string.cancel);
}
else {
refetch();
}
GlobalApplication app = (GlobalApplication)getApplication();
app.sendScreenView(Config.kGAIScreenNameSearch);
}
public void refetch() {
GlobalApplication app = (GlobalApplication) getApplication();
app.setOnLocationListener(this, this);
}
@Override
public void onLocationChanged(Location prevLoc, Location currentLoc) {
GlobalApplication app = (GlobalApplication) getApplication();
app.setOnLocationListener(null, this);
seekBarRadius.setEnabled(true);
btnSearch.setEnabled(true);
}
@Override
public void onLocationRequestDenied() {
MGUtilities.showAlertView(this, R.string.permission_error, R.string.permission_error_details_location);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == Config.RESULT_CODE_CATEGORY && resultCode == RESULT_OK) {
selectedCategories = (ArrayList<DealCategory>) data.getSerializableExtra("categories");
if(selectedCategories != null && selectedCategories.size() > 0) {
TextView tvCategory = (TextView) findViewById(R.id.tvCategory);
String cats = "";
for(int x = 0; x < selectedCategories.size(); x++) {
DealCategory cat = selectedCategories.get(x);
cats += cat.getCategory();
if(x < selectedCategories.size() - 1)
cats += ", ";
}
if(!cats.isEmpty()) {
tvCategory.setText(cats);
}
else {
tvCategory.setText(R.string.all_categories);
}
}
}
if (requestCode == Config.PERMISSION_REQUEST_LOCATION_SETTINGS) {
if(MGUtilities.isLocationEnabled(this))
refetch();
else {
Toast.makeText(this, R.string.location_error_not_turned_on_search, Toast.LENGTH_LONG).show();
}
}
}
public void updateRadius(int progress){
String strSeekVal = String.format("%d %s",
progress,
MGUtilities.getStringFromResource(SearchActivity.this, R.string.km));
TextView tvRadius = (TextView) findViewById(R.id.tvRadius);
tvRadius.setText(strSeekVal);
}
public void showRefresh(boolean show) {
swipeRefresh.setRefreshing(show);
swipeRefresh.setEnabled(show);
}
public void search() {
showRefresh(true);
beginParsing();
}
public ArrayList<Deal> searchLocal() {
EditText txtSearch = (EditText) findViewById(R.id.txtSearch);
String filterSearch = Html.toHtml(new SpannableString(txtSearch.getText().toString()));
String searchStr = MGUtilities.filterInvalidChars(filterSearch);
int radius = seekBarRadius.getProgress();
int countParams = 0;
countParams += searchStr.length() > 0 ? 1 : 0;
countParams += radius > 0 ? 1 : 0;
countParams += selectedCategories != null && selectedCategories.size() > 0 ? 1 : 0;
ArrayList<Deal> array = q.getDeals();
ArrayList<Deal> results = new ArrayList<>();
for(Deal event : array) {
try {
int qualifyCount = 0;
if(searchStr.length() > 0) {
boolean isFound = searchStr.contains(event.getTitle()) ||
searchStr.contains(event.getAddress()) ||
searchStr.contains(event.getDesc()) ||
event.getTitle().contains(searchStr) ||
event.getAddress().contains(searchStr) ||
event.getDesc().contains(searchStr);
if(isFound)
qualifyCount += 1;
}
if(GlobalApplication.currentLocation != null) {
Location loc1 = new Location("Loc1");
loc1.setLatitude(event.getLat());
loc1.setLongitude(event.getLon());
Location loc2 = new Location("Loc2");
loc2.setLatitude(GlobalApplication.currentLocation.getLatitude());
loc2.setLongitude(GlobalApplication.currentLocation.getLongitude());
double distance = loc1.distanceTo(loc2) * Config.METERS_TO_KM;
event.setDistance(distance);
if(distance <= radius)
qualifyCount += 1;
}
ObjectMapper mapper = new ObjectMapper();
DataResponse categories = mapper.readValue(event.getCategories(), DataResponse.class);
if(categories != null && categories.getCategories() != null) {
for(DealCategory cat : categories.getCategories()) {
boolean isFound = false;
for(DealCategory selectedCat : selectedCategories) {
if(selectedCat.getCategory_id() == cat.getCategory_id()) {
isFound = true;
break;
}
}
if(isFound) {
qualifyCount += 1;
break;
}
}
}
if(qualifyCount == countParams)
results.add(event);
}
catch(Exception e) {
e.printStackTrace();
}
}
return results;
}
public void beginParsing() {
if(task != null)
task.cancel(true);
task = new MGAsyncTaskNoDialog(this);
task.setMGAsyncTaskListener(new MGAsyncTaskNoDialog.OnMGAsyncTaskListenerNoDialog() {
DataResponse response;
ArrayList<Deal> events;
@Override
public void onAsyncTaskProgressUpdate(MGAsyncTaskNoDialog asyncTask) { }
@Override
public void onAsyncTaskPreExecute(MGAsyncTaskNoDialog asyncTask) { }
@Override
public void onAsyncTaskPostExecute(MGAsyncTaskNoDialog asyncTask) {
// TODO Auto-generated method stub
updateData(response, events);
}
@Override
public void onAsyncTaskDoInBackground(MGAsyncTaskNoDialog asyncTask) {
// TODO Auto-generated method stub
if(MGUtilities.hasConnection(SearchActivity.this)) {
response = syncData();
}
else{
events = searchLocal();
}
}
});
task.execute();
}
public DataResponse syncData() {
String cats = "";
for(int x = 0; x < selectedCategories.size(); x++) {
DealCategory cat = selectedCategories.get(x);
cats += String.valueOf(cat.getCategory_id());
if (x < selectedCategories.size() - 1)
cats += ",";
}
EditText txtSearch = (EditText) findViewById(R.id.txtSearch);
String filterSearch = Html.toHtml(new SpannableString(txtSearch.getText().toString()));
String searchStr = MGUtilities.filterInvalidChars(filterSearch);
double radius = seekBarRadius.getProgress() * Config.KM_TO_MILES;
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("keywords", searchStr ));
params.add(new BasicNameValuePair("lat", String.valueOf(GlobalApplication.currentLocation.getLatitude()) ));
params.add(new BasicNameValuePair("lon", String.valueOf(GlobalApplication.currentLocation.getLongitude()) ));
params.add(new BasicNameValuePair("category_ids", cats) );
params.add(new BasicNameValuePair("radius", String.valueOf(radius)) );
params.add(new BasicNameValuePair("api_key", Config.API_KEY ));
GlobalApplication.params = params;
DataResponse response = DataParser.getJSONFromUrlWithPostRequest(Config.SEARCH_DEALS_JSON_URL, params);
return response;
}
public void updateData(DataResponse response, ArrayList<Deal> deals) {
showRefresh(false);
if(response != null) {
Status status = response.getStatus();
if(status.getStatus_code() == -1 && response.getDeals() != null ) {
if(response.getDeals().size() == 0) {
Toast.makeText(SearchActivity.this, R.string.no_results_found, Toast.LENGTH_SHORT).show();
return;
}
Intent i = new Intent(this, SearchResultsActivity.class);
i.putExtra("deals", response.getDeals());
startActivity(i);
}
else {
MGUtilities.showAlertView(this, R.string.network_error, status.getStatus_text());
}
}
else if(deals != null && deals.size() > 0) {
GlobalApplication.params = null;
Intent i = new Intent(this, SearchResultsActivity.class);
i.putExtra("deals", deals);
startActivity(i);
}
else {
MGUtilities.showAlertView(this, R.string.network_error, R.string.problems_encountered_while_syncing);
}
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
// Handle action bar actions click
switch (item.getItemId()) {
default:
finish();
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(android.view.Menu menu) {
// if nav drawer is opened, hide the action items
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onDestroy() {
super.onDestroy();
if(task != null)
task.cancel(true);
}
}
从上面的教程链接中,我将以下内容添加到我的Manifest
的AndroidManifest.xml
<activity
android:name="com.projects.activities.SearchActivity">
<intent-filter>
<action android:name="com.google.android.gms.actions.SEARCH_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
然后我将以下内容添加到 SearchActivity.java 文件
中private static final String ACTION_VOICE_SEARCH =
"com.google.android.gms.actions.SEARCH_ACTION";
private void handleVoiceSearch(Intent intent) {
if (intent != null && ACTION_VOICE_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
setSearchViewVisible(true);
searchView.setQuery(query, true);
}
}
在不同的地方和略有不同的方式,我尝试添加
handleVoiceSearch(getIntent());
到SearchActivity.java文件,但我似乎没有太多运气。我正在测试上传到Play商店的Alpha版本。
有什么明显的人可以看到我失踪吗?
由于