GoogleSearch.java revision 18c681a8ab3c5227fb536501572c96b92c914a07
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.quicksearchbox.google; 18 19import com.android.quicksearchbox.R; 20 21import com.google.android.providers.GoogleSettings.Partner; 22 23import android.app.Activity; 24import android.app.SearchManager; 25import android.content.ContentResolver; 26import android.content.Context; 27import android.content.Intent; 28import android.location.Location; 29import android.location.LocationManager; 30import android.net.Uri; 31import android.os.Bundle; 32import android.provider.Browser; 33import android.provider.Settings; 34import android.text.TextUtils; 35import android.util.Log; 36 37import java.io.UnsupportedEncodingException; 38import java.net.URLEncoder; 39import java.util.Locale; 40 41/** 42 * This class is purely here to get search queries and route them to 43 * the global {@link Intent#ACTION_WEB_SEARCH}. 44 */ 45public class GoogleSearch extends Activity { 46 private static final String TAG = "GoogleSearch"; 47 48 // The template URL we should use to format google search requests. 49 private String googleSearchUrlBase = null; 50 51 // "source" parameter for Google search requests from unknown sources (e.g. apps). This will get 52 // prefixed with the string 'android-' before being sent on the wire. 53 final static String GOOGLE_SEARCH_SOURCE_UNKNOWN = "unknown"; 54 55 private LocationUtils mLocationUtils; 56 57 @Override 58 protected void onCreate(Bundle savedInstanceState) { 59 super.onCreate(savedInstanceState); 60 mLocationUtils = LocationUtils.getLocationUtils(this); 61 Intent intent = getIntent(); 62 String action = intent != null ? intent.getAction() : null; 63 if (Intent.ACTION_WEB_SEARCH.equals(action) || Intent.ACTION_SEARCH.equals(action)) { 64 handleWebSearchIntent(intent); 65 } 66 finish(); 67 } 68 69 /** 70 * NOTE: This function is similar to the one found in 71 * com.google.android.providers.enhancedgooglesearch.Launcher. If you are changing this 72 * make sure you change both. 73 */ 74 private void handleWebSearchIntent(Intent intent) { 75 String query = intent.getStringExtra(SearchManager.QUERY); 76 if (TextUtils.isEmpty(query)) { 77 Log.w(TAG, "Got search intent with no query."); 78 return; 79 } 80 81 if (googleSearchUrlBase == null) { 82 Locale l = Locale.getDefault(); 83 String language = l.getLanguage(); 84 String country = l.getCountry().toLowerCase(); 85 // Chinese and Portuguese have two langauge variants. 86 if ("zh".equals(language)) { 87 if ("cn".equals(country)) { 88 language = "zh-CN"; 89 } else if ("tw".equals(country)) { 90 language = "zh-TW"; 91 } 92 } else if ("pt".equals(language)) { 93 if ("br".equals(country)) { 94 language = "pt-BR"; 95 } else if ("pt".equals(country)) { 96 language = "pt-PT"; 97 } 98 } 99 googleSearchUrlBase = getResources().getString( 100 R.string.google_search_base, language, country) 101 + "client=ms-" 102 + Partner.getString(this.getContentResolver(), Partner.CLIENT_ID); 103 } 104 105 // If the caller specified a 'source' url parameter, use that and if not use default. 106 Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA); 107 String source = GOOGLE_SEARCH_SOURCE_UNKNOWN; 108 if (appSearchData != null) { 109 source = appSearchData.getString(SearchManager.SOURCE); 110 } 111 112 // The browser can pass along an application id which it uses to figure out which 113 // window to place a new search into. So if this exists, we'll pass it back to 114 // the browser. Otherwise, add our own package name as the application id, so that 115 // the browser can organize all searches launched from this provider together. 116 String applicationId = intent.getStringExtra(Browser.EXTRA_APPLICATION_ID); 117 if (applicationId == null) { 118 applicationId = getPackageName(); 119 } 120 121 try { 122 String searchUri = googleSearchUrlBase 123 + "&source=android-" + source 124 + "&q=" + URLEncoder.encode(query, "UTF-8"); 125 Intent launchUriIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri)); 126 launchUriIntent.putExtra(Browser.EXTRA_APPLICATION_ID, applicationId); 127 launchUriIntent.putExtra(Browser.EXTRA_POST_DATA, getLocationData()); 128 launchUriIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 129 startActivity(launchUriIntent); 130 } catch (UnsupportedEncodingException e) { 131 Log.w(TAG, "Error", e); 132 } 133 } 134 135 private byte[] getLocationData() { 136 byte[] postData = null; 137 ContentResolver cr = getContentResolver(); 138 139 // Don't send any location if the system does not have GoogleSettingsProvider. 140 if (!mLocationUtils.systemHasGoogleSettingsProvider()) return postData; 141 142 if (!mLocationUtils.userRespondedToLocationOptIn()) { 143 // Bring up the consent dialog if it the user has yet responded to it. We 144 // will not send the location info for this query. 145 mLocationUtils.showLocationOptIn(); 146 } else if (mLocationUtils.userAcceptedLocationOptIn() && 147 isLocationProviderEnabled(cr, LocationManager.NETWORK_PROVIDER)) { 148 Location location = ((LocationManager) getSystemService( 149 Context.LOCATION_SERVICE)).getLastKnownLocation( 150 LocationManager.NETWORK_PROVIDER); 151 if (location != null) { 152 StringBuilder str = new StringBuilder("action=devloc&sll="); 153 str.append(location.getLatitude()).append(',').append(location.getLongitude()); 154 postData = str.toString().getBytes(); 155 } 156 } 157 return postData; 158 } 159 160 /** 161 * Utility method copied from android.provider.Settings.Secure. 162 * 163 * Helper method for determining if a location provider is enabled. 164 * @param cr the content resolver to use 165 * @param provider the location provider to query 166 * @return true if the provider is enabled 167 */ 168 private static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { 169 String allowedProviders = Settings.Secure.getString(cr, 170 Settings.Secure.LOCATION_PROVIDERS_ALLOWED); 171 if (allowedProviders != null) { 172 return (allowedProviders.equals(provider) || 173 allowedProviders.contains("," + provider + ",") || 174 allowedProviders.startsWith(provider + ",") || 175 allowedProviders.endsWith("," + provider)); 176 } 177 return false; 178 } 179 180} 181