Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 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 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 17 | package com.android.printspooler.ui; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 18 | |
| 19 | import android.app.Activity; |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 20 | import android.app.LoaderManager; |
Svetoslav Ganov | 860f8a6 | 2013-09-14 00:59:03 -0700 | [diff] [blame] | 21 | import android.content.Context; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 22 | import android.content.Intent; |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 23 | import android.content.IntentSender.SendIntentException; |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 24 | import android.content.Loader; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 25 | import android.content.pm.PackageInfo; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 26 | import android.content.pm.PackageManager.NameNotFoundException; |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 27 | import android.database.DataSetObserver; |
Svetoslav | 39e71de | 2013-10-02 19:30:32 -0700 | [diff] [blame] | 28 | import android.graphics.drawable.Drawable; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 29 | import android.os.Bundle; |
Svetoslav Ganov | 860f8a6 | 2013-09-14 00:59:03 -0700 | [diff] [blame] | 30 | import android.print.PrintManager; |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 31 | import android.print.PrintServicesLoader; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 32 | import android.print.PrinterId; |
| 33 | import android.print.PrinterInfo; |
| 34 | import android.printservice.PrintServiceInfo; |
Svetoslav Ganov | 0ea7d1e | 2013-10-05 11:46:48 -0700 | [diff] [blame] | 35 | import android.provider.Settings; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 36 | import android.text.TextUtils; |
Svetoslav Ganov | 860f8a6 | 2013-09-14 00:59:03 -0700 | [diff] [blame] | 37 | import android.util.Log; |
Philip P. Moltmann | 443075a | 2016-01-26 13:04:21 -0800 | [diff] [blame] | 38 | import android.util.TypedValue; |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 39 | import android.view.ContextMenu; |
| 40 | import android.view.ContextMenu.ContextMenuInfo; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 41 | import android.view.Menu; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 42 | import android.view.MenuItem; |
| 43 | import android.view.View; |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 44 | import android.view.View.OnClickListener; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 45 | import android.view.ViewGroup; |
Svetoslav | 53e8a26 | 2013-10-08 11:25:32 -0700 | [diff] [blame] | 46 | import android.view.accessibility.AccessibilityManager; |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 47 | import android.widget.AdapterView; |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 48 | import android.widget.AdapterView.AdapterContextMenuInfo; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 49 | import android.widget.BaseAdapter; |
| 50 | import android.widget.Filter; |
| 51 | import android.widget.Filterable; |
Svetoslav | 39e71de | 2013-10-02 19:30:32 -0700 | [diff] [blame] | 52 | import android.widget.ImageView; |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 53 | import android.widget.LinearLayout; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 54 | import android.widget.ListView; |
| 55 | import android.widget.SearchView; |
| 56 | import android.widget.TextView; |
Philip P. Moltmann | 1f46779 | 2016-01-08 14:02:57 -0800 | [diff] [blame] | 57 | import android.widget.Toast; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 58 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 59 | import com.android.printspooler.R; |
| 60 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 61 | import java.util.ArrayList; |
| 62 | import java.util.List; |
| 63 | |
| 64 | /** |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 65 | * This is an activity for selecting a printer. |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 66 | */ |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 67 | public final class SelectPrinterActivity extends Activity implements |
| 68 | LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> { |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 69 | |
Svetoslav Ganov | 860f8a6 | 2013-09-14 00:59:03 -0700 | [diff] [blame] | 70 | private static final String LOG_TAG = "SelectPrinterFragment"; |
| 71 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 72 | private static final int LOADER_ID_PRINT_REGISTRY = 1; |
| 73 | private static final int LOADER_ID_PRINT_REGISTRY_INT = 2; |
| 74 | private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 3; |
| 75 | |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 76 | public static final String INTENT_EXTRA_PRINTER = "INTENT_EXTRA_PRINTER"; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 77 | |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 78 | private static final String EXTRA_PRINTER = "EXTRA_PRINTER"; |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 79 | private static final String EXTRA_PRINTER_ID = "EXTRA_PRINTER_ID"; |
| 80 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 81 | private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE"; |
| 82 | |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 83 | /** If there are any enabled print services */ |
Philip P. Moltmann | 953639c | 2015-11-11 15:30:16 -0800 | [diff] [blame] | 84 | private boolean mHasEnabledPrintServices; |
| 85 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 86 | private PrinterRegistry mPrinterRegistry; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 87 | |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 88 | private ListView mListView; |
| 89 | |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 90 | private AnnounceFilterResult mAnnounceFilterResult; |
| 91 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 92 | private void startAddPrinterActivity() { |
| 93 | startActivity(new Intent(this, AddPrinterActivity.class)); |
| 94 | } |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 95 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 96 | @Override |
| 97 | public void onCreate(Bundle savedInstanceState) { |
| 98 | super.onCreate(savedInstanceState); |
Svetoslav | 309f6a0 | 2014-08-18 16:10:59 -0700 | [diff] [blame] | 99 | getActionBar().setIcon(R.drawable.ic_print); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 100 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 101 | setContentView(R.layout.select_printer_activity); |
| 102 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 103 | mPrinterRegistry = new PrinterRegistry(this, null, LOADER_ID_PRINT_REGISTRY, |
| 104 | LOADER_ID_PRINT_REGISTRY_INT); |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 105 | |
| 106 | // Hook up the list view. |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 107 | mListView = (ListView) findViewById(android.R.id.list); |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 108 | final DestinationAdapter adapter = new DestinationAdapter(); |
| 109 | adapter.registerDataSetObserver(new DataSetObserver() { |
| 110 | @Override |
| 111 | public void onChanged() { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 112 | if (!isFinishing() && adapter.getCount() <= 0) { |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 113 | updateEmptyView(adapter); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | @Override |
| 118 | public void onInvalidated() { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 119 | if (!isFinishing()) { |
Svetoslav Ganov | 24c686b | 2013-10-05 18:52:06 -0700 | [diff] [blame] | 120 | updateEmptyView(adapter); |
| 121 | } |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 122 | } |
| 123 | }); |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 124 | mListView.setAdapter(adapter); |
| 125 | |
| 126 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { |
| 127 | @Override |
| 128 | public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 129 | if (!((DestinationAdapter) mListView.getAdapter()).isActionable(position)) { |
| 130 | return; |
| 131 | } |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 132 | |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 133 | PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position); |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 134 | |
| 135 | if (printer == null) { |
| 136 | startAddPrinterActivity(); |
| 137 | } else { |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 138 | onPrinterSelected(printer); |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 139 | } |
| 140 | } |
| 141 | }); |
| 142 | |
| 143 | findViewById(R.id.button).setOnClickListener(new OnClickListener() { |
| 144 | @Override public void onClick(View v) { |
| 145 | startAddPrinterActivity(); |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 146 | } |
| 147 | }); |
| 148 | |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 149 | registerForContextMenu(mListView); |
Philip P. Moltmann | 1f46779 | 2016-01-08 14:02:57 -0800 | [diff] [blame] | 150 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 151 | getLoaderManager().initLoader(LOADER_ID_ENABLED_PRINT_SERVICES, null, this); |
| 152 | |
| 153 | // On first creation: |
| 154 | // |
| 155 | // If no services are installed, instantly open add printer dialog. |
| 156 | // If some are disabled and some are enabled show a toast to notify the user |
| 157 | if (savedInstanceState == null || !savedInstanceState.getBoolean(KEY_NOT_FIRST_CREATE)) { |
| 158 | List<PrintServiceInfo> allServices = |
| 159 | ((PrintManager) getSystemService(Context.PRINT_SERVICE)) |
| 160 | .getPrintServices(PrintManager.ALL_SERVICES); |
| 161 | boolean hasEnabledServices = false; |
| 162 | boolean hasDisabledServices = false; |
| 163 | |
| 164 | if (allServices != null) { |
| 165 | final int numServices = allServices.size(); |
| 166 | for (int i = 0; i < numServices; i++) { |
| 167 | if (allServices.get(i).isEnabled()) { |
| 168 | hasEnabledServices = true; |
| 169 | } else { |
| 170 | hasDisabledServices = true; |
| 171 | } |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | if (!hasEnabledServices) { |
| 176 | startAddPrinterActivity(); |
| 177 | } else if (hasDisabledServices) { |
| 178 | String disabledServicesSetting = Settings.Secure.getString(getContentResolver(), |
| 179 | Settings.Secure.DISABLED_PRINT_SERVICES); |
| 180 | if (!TextUtils.isEmpty(disabledServicesSetting)) { |
| 181 | Toast.makeText(this, getString(R.string.print_services_disabled_toast), |
| 182 | Toast.LENGTH_LONG).show(); |
| 183 | } |
| 184 | } |
Philip P. Moltmann | 1f46779 | 2016-01-08 14:02:57 -0800 | [diff] [blame] | 185 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | @Override |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 189 | protected void onSaveInstanceState(Bundle outState) { |
| 190 | super.onSaveInstanceState(outState); |
| 191 | outState.putBoolean(KEY_NOT_FIRST_CREATE, true); |
| 192 | } |
| 193 | |
| 194 | @Override |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 195 | public boolean onCreateOptionsMenu(Menu menu) { |
| 196 | super.onCreateOptionsMenu(menu); |
| 197 | |
| 198 | getMenuInflater().inflate(R.menu.select_printer_activity, menu); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 199 | |
| 200 | MenuItem searchItem = menu.findItem(R.id.action_search); |
| 201 | SearchView searchView = (SearchView) searchItem.getActionView(); |
| 202 | searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { |
| 203 | @Override |
| 204 | public boolean onQueryTextSubmit(String query) { |
| 205 | return true; |
| 206 | } |
| 207 | |
| 208 | @Override |
| 209 | public boolean onQueryTextChange(String searchString) { |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 210 | ((DestinationAdapter) mListView.getAdapter()).getFilter().filter(searchString); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 211 | return true; |
| 212 | } |
| 213 | }); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 214 | searchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { |
| 215 | @Override |
| 216 | public void onViewAttachedToWindow(View view) { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 217 | if (AccessibilityManager.getInstance(SelectPrinterActivity.this).isEnabled()) { |
Svetoslav | 53e8a26 | 2013-10-08 11:25:32 -0700 | [diff] [blame] | 218 | view.announceForAccessibility(getString( |
| 219 | R.string.print_search_box_shown_utterance)); |
| 220 | } |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 221 | } |
| 222 | @Override |
| 223 | public void onViewDetachedFromWindow(View view) { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 224 | if (!isFinishing() && AccessibilityManager.getInstance( |
| 225 | SelectPrinterActivity.this).isEnabled()) { |
Svetoslav | 53e8a26 | 2013-10-08 11:25:32 -0700 | [diff] [blame] | 226 | view.announceForAccessibility(getString( |
| 227 | R.string.print_search_box_hidden_utterance)); |
| 228 | } |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 229 | } |
| 230 | }); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 231 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 232 | return true; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | @Override |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 236 | public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { |
| 237 | if (view == mListView) { |
| 238 | final int position = ((AdapterContextMenuInfo) menuInfo).position; |
| 239 | PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position); |
| 240 | |
| 241 | menu.setHeaderTitle(printer.getName()); |
| 242 | |
| 243 | // Add the select menu item if applicable. |
| 244 | if (printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE) { |
| 245 | MenuItem selectItem = menu.add(Menu.NONE, R.string.print_select_printer, |
| 246 | Menu.NONE, R.string.print_select_printer); |
| 247 | Intent intent = new Intent(); |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 248 | intent.putExtra(EXTRA_PRINTER, printer); |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 249 | selectItem.setIntent(intent); |
| 250 | } |
| 251 | |
| 252 | // Add the forget menu item if applicable. |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 253 | if (mPrinterRegistry.isFavoritePrinter(printer.getId())) { |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 254 | MenuItem forgetItem = menu.add(Menu.NONE, R.string.print_forget_printer, |
| 255 | Menu.NONE, R.string.print_forget_printer); |
| 256 | Intent intent = new Intent(); |
| 257 | intent.putExtra(EXTRA_PRINTER_ID, printer.getId()); |
| 258 | forgetItem.setIntent(intent); |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | @Override |
| 264 | public boolean onContextItemSelected(MenuItem item) { |
| 265 | switch (item.getItemId()) { |
| 266 | case R.string.print_select_printer: { |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 267 | PrinterInfo printer = item.getIntent().getParcelableExtra(EXTRA_PRINTER); |
| 268 | onPrinterSelected(printer); |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 269 | } return true; |
| 270 | |
| 271 | case R.string.print_forget_printer: { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 272 | PrinterId printerId = item.getIntent().getParcelableExtra(EXTRA_PRINTER_ID); |
| 273 | mPrinterRegistry.forgetFavoritePrinter(printerId); |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 274 | } return true; |
| 275 | } |
| 276 | return false; |
| 277 | } |
| 278 | |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 279 | /** |
| 280 | * Adjust the UI if the enabled print services changed. |
| 281 | */ |
| 282 | private synchronized void onPrintServicesUpdate() { |
Philip P. Moltmann | 953639c | 2015-11-11 15:30:16 -0800 | [diff] [blame] | 283 | updateEmptyView((DestinationAdapter)mListView.getAdapter()); |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 284 | invalidateOptionsMenu(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 285 | } |
| 286 | |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 287 | @Override |
| 288 | public void onStart() { |
| 289 | super.onStart(); |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 290 | onPrintServicesUpdate(); |
| 291 | } |
| 292 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 293 | @Override |
Svetoslav | ebec468 | 2013-10-08 17:17:08 -0700 | [diff] [blame] | 294 | public void onPause() { |
| 295 | if (mAnnounceFilterResult != null) { |
| 296 | mAnnounceFilterResult.remove(); |
| 297 | } |
| 298 | super.onPause(); |
| 299 | } |
| 300 | |
| 301 | @Override |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 302 | public void onStop() { |
Philip P. Moltmann | 03755a1 | 2015-11-25 13:35:41 -0800 | [diff] [blame] | 303 | super.onStop(); |
| 304 | } |
| 305 | |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 306 | private void onPrinterSelected(PrinterInfo printer) { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 307 | Intent intent = new Intent(); |
Philip P. Moltmann | 63ce0b7 | 2016-03-08 11:16:56 -0800 | [diff] [blame] | 308 | intent.putExtra(INTENT_EXTRA_PRINTER, printer); |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 309 | setResult(RESULT_OK, intent); |
| 310 | finish(); |
| 311 | } |
| 312 | |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 313 | public void updateEmptyView(DestinationAdapter adapter) { |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 314 | if (mListView.getEmptyView() == null) { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 315 | View emptyView = findViewById(R.id.empty_print_state); |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 316 | mListView.setEmptyView(emptyView); |
Svetoslav Ganov | 24c686b | 2013-10-05 18:52:06 -0700 | [diff] [blame] | 317 | } |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 318 | TextView titleView = (TextView) findViewById(R.id.title); |
| 319 | View progressBar = findViewById(R.id.progress_bar); |
Philip P. Moltmann | 953639c | 2015-11-11 15:30:16 -0800 | [diff] [blame] | 320 | if (!mHasEnabledPrintServices) { |
| 321 | titleView.setText(R.string.print_no_print_services); |
| 322 | progressBar.setVisibility(View.GONE); |
| 323 | } else if (adapter.getUnfilteredCount() <= 0) { |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 324 | titleView.setText(R.string.print_searching_for_printers); |
| 325 | progressBar.setVisibility(View.VISIBLE); |
| 326 | } else { |
| 327 | titleView.setText(R.string.print_no_printers); |
| 328 | progressBar.setVisibility(View.GONE); |
| 329 | } |
| 330 | } |
| 331 | |
Svetoslav | ebec468 | 2013-10-08 17:17:08 -0700 | [diff] [blame] | 332 | private void announceSearchResultIfNeeded() { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 333 | if (AccessibilityManager.getInstance(this).isEnabled()) { |
Svetoslav | ebec468 | 2013-10-08 17:17:08 -0700 | [diff] [blame] | 334 | if (mAnnounceFilterResult == null) { |
| 335 | mAnnounceFilterResult = new AnnounceFilterResult(); |
| 336 | } |
| 337 | mAnnounceFilterResult.post(); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 338 | } |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 339 | } |
| 340 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 341 | @Override |
| 342 | public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) { |
| 343 | return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this, |
| 344 | PrintManager.ENABLED_SERVICES); |
| 345 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 346 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 347 | @Override |
| 348 | public void onLoadFinished(Loader<List<PrintServiceInfo>> loader, |
| 349 | List<PrintServiceInfo> data) { |
| 350 | if (data == null || data.isEmpty()) { |
| 351 | mHasEnabledPrintServices = false; |
| 352 | } else { |
| 353 | mHasEnabledPrintServices = true; |
| 354 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 355 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 356 | onPrintServicesUpdate(); |
| 357 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 358 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 359 | @Override |
| 360 | public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) { |
| 361 | if (!isFinishing()) { |
| 362 | onLoadFinished(loader, null); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 363 | } |
| 364 | } |
| 365 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 366 | private final class DestinationAdapter extends BaseAdapter implements Filterable { |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 367 | |
| 368 | private final Object mLock = new Object(); |
| 369 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 370 | private final List<PrinterInfo> mPrinters = new ArrayList<>(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 371 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 372 | private final List<PrinterInfo> mFilteredPrinters = new ArrayList<>(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 373 | |
| 374 | private CharSequence mLastSearchString; |
| 375 | |
| 376 | public DestinationAdapter() { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 377 | mPrinterRegistry.setOnPrintersChangeListener(new PrinterRegistry.OnPrintersChangeListener() { |
| 378 | @Override |
| 379 | public void onPrintersChanged(List<PrinterInfo> printers) { |
| 380 | synchronized (mLock) { |
| 381 | mPrinters.clear(); |
| 382 | mPrinters.addAll(printers); |
| 383 | mFilteredPrinters.clear(); |
| 384 | mFilteredPrinters.addAll(printers); |
| 385 | if (!TextUtils.isEmpty(mLastSearchString)) { |
| 386 | getFilter().filter(mLastSearchString); |
| 387 | } |
| 388 | } |
| 389 | notifyDataSetChanged(); |
| 390 | } |
| 391 | |
| 392 | @Override |
| 393 | public void onPrintersInvalid() { |
| 394 | synchronized (mLock) { |
| 395 | mPrinters.clear(); |
| 396 | mFilteredPrinters.clear(); |
| 397 | } |
| 398 | notifyDataSetInvalidated(); |
| 399 | } |
| 400 | }); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 401 | } |
| 402 | |
| 403 | @Override |
| 404 | public Filter getFilter() { |
| 405 | return new Filter() { |
| 406 | @Override |
| 407 | protected FilterResults performFiltering(CharSequence constraint) { |
| 408 | synchronized (mLock) { |
| 409 | if (TextUtils.isEmpty(constraint)) { |
| 410 | return null; |
| 411 | } |
| 412 | FilterResults results = new FilterResults(); |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 413 | List<PrinterInfo> filteredPrinters = new ArrayList<>(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 414 | String constraintLowerCase = constraint.toString().toLowerCase(); |
| 415 | final int printerCount = mPrinters.size(); |
| 416 | for (int i = 0; i < printerCount; i++) { |
| 417 | PrinterInfo printer = mPrinters.get(i); |
Philip P. Moltmann | e58d8ff | 2016-01-26 10:08:31 -0800 | [diff] [blame] | 418 | String description = printer.getDescription(); |
| 419 | if (printer.getName().toLowerCase().contains(constraintLowerCase) |
| 420 | || description != null && description.toLowerCase() |
| 421 | .contains(constraintLowerCase)) { |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 422 | filteredPrinters.add(printer); |
| 423 | } |
| 424 | } |
| 425 | results.values = filteredPrinters; |
| 426 | results.count = filteredPrinters.size(); |
| 427 | return results; |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | @Override |
| 432 | @SuppressWarnings("unchecked") |
| 433 | protected void publishResults(CharSequence constraint, FilterResults results) { |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 434 | final boolean resultCountChanged; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 435 | synchronized (mLock) { |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 436 | final int oldPrinterCount = mFilteredPrinters.size(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 437 | mLastSearchString = constraint; |
| 438 | mFilteredPrinters.clear(); |
| 439 | if (results == null) { |
| 440 | mFilteredPrinters.addAll(mPrinters); |
| 441 | } else { |
| 442 | List<PrinterInfo> printers = (List<PrinterInfo>) results.values; |
| 443 | mFilteredPrinters.addAll(printers); |
| 444 | } |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 445 | resultCountChanged = (oldPrinterCount != mFilteredPrinters.size()); |
| 446 | } |
| 447 | if (resultCountChanged) { |
Svetoslav | ebec468 | 2013-10-08 17:17:08 -0700 | [diff] [blame] | 448 | announceSearchResultIfNeeded(); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 449 | } |
| 450 | notifyDataSetChanged(); |
| 451 | } |
| 452 | }; |
| 453 | } |
| 454 | |
Svetoslav Ganov | 264c566 | 2013-10-05 12:58:17 -0700 | [diff] [blame] | 455 | public int getUnfilteredCount() { |
| 456 | synchronized (mLock) { |
| 457 | return mPrinters.size(); |
| 458 | } |
| 459 | } |
| 460 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 461 | @Override |
| 462 | public int getCount() { |
| 463 | synchronized (mLock) { |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 464 | if (mFilteredPrinters.isEmpty()) { |
| 465 | return 0; |
| 466 | } else { |
| 467 | // Add "add printer" item to the end of the list. If the list is empty there is |
| 468 | // a link on the empty view |
| 469 | return mFilteredPrinters.size() + 1; |
| 470 | } |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | @Override |
| 475 | public int getViewTypeCount() { |
| 476 | return 2; |
| 477 | } |
| 478 | |
| 479 | @Override |
| 480 | public int getItemViewType(int position) { |
| 481 | // Use separate view types for the "add printer" item an the items referring to printers |
| 482 | if (getItem(position) == null) { |
| 483 | return 0; |
| 484 | } else { |
| 485 | return 1; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 486 | } |
| 487 | } |
| 488 | |
| 489 | @Override |
| 490 | public Object getItem(int position) { |
| 491 | synchronized (mLock) { |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 492 | if (position < mFilteredPrinters.size()) { |
| 493 | return mFilteredPrinters.get(position); |
| 494 | } else { |
| 495 | // Return null to mark this as the "add printer item" |
| 496 | return null; |
| 497 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 498 | } |
| 499 | } |
| 500 | |
| 501 | @Override |
| 502 | public long getItemId(int position) { |
| 503 | return position; |
| 504 | } |
| 505 | |
| 506 | @Override |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 507 | public View getDropDownView(int position, View convertView, ViewGroup parent) { |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 508 | return getView(position, convertView, parent); |
| 509 | } |
| 510 | |
| 511 | @Override |
| 512 | public View getView(int position, View convertView, ViewGroup parent) { |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 513 | final PrinterInfo printer = (PrinterInfo) getItem(position); |
| 514 | |
| 515 | // Handle "add printer item" |
| 516 | if (printer == null) { |
| 517 | if (convertView == null) { |
| 518 | convertView = getLayoutInflater().inflate(R.layout.add_printer_list_item, |
| 519 | parent, false); |
| 520 | } |
| 521 | |
| 522 | return convertView; |
| 523 | } |
| 524 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 525 | if (convertView == null) { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 526 | convertView = getLayoutInflater().inflate( |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 527 | R.layout.printer_list_item, parent, false); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 528 | } |
| 529 | |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 530 | convertView.setEnabled(isActionable(position)); |
Svetoslav Ganov | 69b91e0 | 2013-10-07 22:17:30 -0700 | [diff] [blame] | 531 | |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 532 | |
| 533 | CharSequence title = printer.getName(); |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 534 | Drawable icon = printer.loadIcon(SelectPrinterActivity.this); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 535 | |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 536 | CharSequence printServiceLabel; |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 537 | try { |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 538 | PackageInfo packageInfo = getPackageManager().getPackageInfo( |
| 539 | printer.getId().getServiceName().getPackageName(), 0); |
| 540 | |
| 541 | printServiceLabel = packageInfo.applicationInfo.loadLabel(getPackageManager()); |
| 542 | } catch (NameNotFoundException e) { |
| 543 | printServiceLabel = null; |
| 544 | } |
| 545 | |
| 546 | CharSequence description = printer.getDescription(); |
| 547 | |
| 548 | CharSequence subtitle; |
Philip P. Moltmann | 5462e88 | 2016-01-20 13:55:38 -0800 | [diff] [blame] | 549 | if (TextUtils.isEmpty(printServiceLabel)) { |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 550 | subtitle = description; |
Philip P. Moltmann | 5462e88 | 2016-01-20 13:55:38 -0800 | [diff] [blame] | 551 | } else if (TextUtils.isEmpty(description)) { |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 552 | subtitle = printServiceLabel; |
| 553 | } else { |
| 554 | subtitle = getString(R.string.printer_extended_description_template, |
| 555 | printServiceLabel, description); |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 556 | } |
| 557 | |
| 558 | TextView titleView = (TextView) convertView.findViewById(R.id.title); |
| 559 | titleView.setText(title); |
| 560 | |
| 561 | TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle); |
| 562 | if (!TextUtils.isEmpty(subtitle)) { |
| 563 | subtitleView.setText(subtitle); |
| 564 | subtitleView.setVisibility(View.VISIBLE); |
| 565 | } else { |
| 566 | subtitleView.setText(null); |
| 567 | subtitleView.setVisibility(View.GONE); |
| 568 | } |
| 569 | |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 570 | LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info); |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 571 | if (printer.getInfoIntent() != null) { |
| 572 | moreInfoView.setVisibility(View.VISIBLE); |
| 573 | moreInfoView.setOnClickListener(new OnClickListener() { |
| 574 | @Override |
| 575 | public void onClick(View v) { |
| 576 | try { |
Philip P. Moltmann | 443075a | 2016-01-26 13:04:21 -0800 | [diff] [blame] | 577 | startIntentSender(printer.getInfoIntent().getIntentSender(), null, 0, 0, |
| 578 | 0); |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 579 | } catch (SendIntentException e) { |
| 580 | Log.e(LOG_TAG, "Could not execute pending info intent: %s", e); |
| 581 | } |
| 582 | } |
| 583 | }); |
Philip P. Moltmann | 443075a | 2016-01-26 13:04:21 -0800 | [diff] [blame] | 584 | } else { |
| 585 | moreInfoView.setVisibility(View.GONE); |
Philip P. Moltmann | bb9f686 | 2015-12-01 14:44:24 -0800 | [diff] [blame] | 586 | } |
Svetoslav | 39e71de | 2013-10-02 19:30:32 -0700 | [diff] [blame] | 587 | |
| 588 | ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); |
| 589 | if (icon != null) { |
Svetoslav | 39e71de | 2013-10-02 19:30:32 -0700 | [diff] [blame] | 590 | iconView.setVisibility(View.VISIBLE); |
Philip P. Moltmann | 443075a | 2016-01-26 13:04:21 -0800 | [diff] [blame] | 591 | if (!isActionable(position)) { |
| 592 | icon.mutate(); |
| 593 | |
| 594 | TypedValue value = new TypedValue(); |
| 595 | getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true); |
| 596 | icon.setAlpha((int)(value.getFloat() * 255)); |
| 597 | } |
| 598 | iconView.setImageDrawable(icon); |
Svetoslav | 39e71de | 2013-10-02 19:30:32 -0700 | [diff] [blame] | 599 | } else { |
| 600 | iconView.setVisibility(View.GONE); |
| 601 | } |
| 602 | |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 603 | return convertView; |
| 604 | } |
| 605 | |
Svetoslav | 1c664b6 | 2013-11-04 12:30:08 -0800 | [diff] [blame] | 606 | public boolean isActionable(int position) { |
Svetoslav Ganov | 69b91e0 | 2013-10-07 22:17:30 -0700 | [diff] [blame] | 607 | PrinterInfo printer = (PrinterInfo) getItem(position); |
Philip P. Moltmann | 66c9659 | 2016-02-24 11:32:43 -0800 | [diff] [blame] | 608 | |
| 609 | if (printer == null) { |
| 610 | return true; |
| 611 | } else { |
| 612 | return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE; |
| 613 | } |
Svetoslav Ganov | 69b91e0 | 2013-10-07 22:17:30 -0700 | [diff] [blame] | 614 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 615 | } |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 616 | |
| 617 | private final class AnnounceFilterResult implements Runnable { |
| 618 | private static final int SEARCH_RESULT_ANNOUNCEMENT_DELAY = 1000; // 1 sec |
| 619 | |
| 620 | public void post() { |
| 621 | remove(); |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 622 | mListView.postDelayed(this, SEARCH_RESULT_ANNOUNCEMENT_DELAY); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 623 | } |
| 624 | |
| 625 | public void remove() { |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 626 | mListView.removeCallbacks(this); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 627 | } |
| 628 | |
| 629 | @Override |
| 630 | public void run() { |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 631 | final int count = mListView.getAdapter().getCount(); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 632 | final String text; |
| 633 | if (count <= 0) { |
| 634 | text = getString(R.string.print_no_printers); |
| 635 | } else { |
Svetoslav | a798c0a | 2014-05-15 10:47:19 -0700 | [diff] [blame] | 636 | text = getResources().getQuantityString( |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 637 | R.plurals.print_search_result_count_utterance, count, count); |
| 638 | } |
Svetoslav Ganov | ed513d7e | 2013-10-17 09:53:05 -0700 | [diff] [blame] | 639 | mListView.announceForAccessibility(text); |
Svetoslav Ganov | 56ddf1f | 2013-10-05 19:55:49 -0700 | [diff] [blame] | 640 | } |
| 641 | } |
Svetoslav | 269403b | 2013-08-14 17:31:04 -0700 | [diff] [blame] | 642 | } |