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 17 package com.android.settings.print; 18 19 import android.app.Activity; 20 import android.app.LoaderManager; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentSender.SendIntentException; 25 import android.content.Loader; 26 import android.content.pm.ResolveInfo; 27 import android.database.DataSetObserver; 28 import android.graphics.Color; 29 import android.graphics.drawable.ColorDrawable; 30 import android.graphics.drawable.Drawable; 31 import android.os.Bundle; 32 import android.print.PrintManager; 33 import android.print.PrintServicesLoader; 34 import android.print.PrinterDiscoverySession; 35 import android.print.PrinterDiscoverySession.OnPrintersChangeListener; 36 import android.print.PrinterId; 37 import android.print.PrinterInfo; 38 import android.printservice.PrintServiceInfo; 39 import android.text.TextUtils; 40 import android.util.Log; 41 import android.util.TypedValue; 42 import android.view.Menu; 43 import android.view.MenuInflater; 44 import android.view.MenuItem; 45 import android.view.View; 46 import android.view.ViewGroup; 47 import android.view.View.OnClickListener; 48 import android.view.accessibility.AccessibilityManager; 49 import android.widget.AdapterView; 50 import android.widget.BaseAdapter; 51 import android.widget.Filter; 52 import android.widget.Filterable; 53 import android.widget.ImageView; 54 import android.widget.LinearLayout; 55 import android.widget.ListView; 56 import android.widget.SearchView; 57 import android.widget.Switch; 58 import android.widget.TextView; 59 60 import com.android.internal.logging.MetricsProto.MetricsEvent; 61 import com.android.settings.R; 62 import com.android.settings.SettingsActivity; 63 import com.android.settings.SettingsPreferenceFragment; 64 import com.android.settings.widget.SwitchBar; 65 import com.android.settings.widget.ToggleSwitch; 66 67 import java.util.ArrayList; 68 import java.util.LinkedHashMap; 69 import java.util.List; 70 import java.util.Map; 71 72 /** 73 * Fragment with print service settings. 74 */ 75 public class PrintServiceSettingsFragment extends SettingsPreferenceFragment 76 implements SwitchBar.OnSwitchChangeListener, 77 LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> { 78 79 private static final String LOG_TAG = "PrintServiceSettingsFragment"; 80 81 private static final int LOADER_ID_PRINTERS_LOADER = 1; 82 private static final int LOADER_ID_PRINT_SERVICE_LOADER = 2; 83 84 private final DataSetObserver mDataObserver = new DataSetObserver() { 85 @Override 86 public void onChanged() { 87 invalidateOptionsMenuIfNeeded(); 88 updateEmptyView(); 89 } 90 91 @Override 92 public void onInvalidated() { 93 invalidateOptionsMenuIfNeeded(); 94 } 95 96 private void invalidateOptionsMenuIfNeeded() { 97 final int unfilteredItemCount = mPrintersAdapter.getUnfilteredCount(); 98 if ((mLastUnfilteredItemCount <= 0 && unfilteredItemCount > 0) 99 || mLastUnfilteredItemCount > 0 && unfilteredItemCount <= 0) { 100 getActivity().invalidateOptionsMenu(); 101 } 102 mLastUnfilteredItemCount = unfilteredItemCount; 103 } 104 }; 105 106 private SwitchBar mSwitchBar; 107 private ToggleSwitch mToggleSwitch; 108 109 private String mPreferenceKey; 110 111 private Intent mSettingsIntent; 112 113 private Intent mAddPrintersIntent; 114 115 private ComponentName mComponentName; 116 117 private PrintersAdapter mPrintersAdapter; 118 119 // TODO: Showing sub-sub fragment does not handle the activity title 120 // so we do it but this is wrong. Do a real fix when there is time. 121 private CharSequence mOldActivityTitle; 122 123 private int mLastUnfilteredItemCount; 124 125 private boolean mServiceEnabled; 126 127 private SearchView mSearchView; 128 129 @Override 130 protected int getMetricsCategory() { 131 return MetricsEvent.PRINT_SERVICE_SETTINGS; 132 } 133 134 @Override 135 public void onCreate(Bundle icicle) { 136 super.onCreate(icicle); 137 138 mServiceEnabled = getArguments().getBoolean(PrintSettingsFragment.EXTRA_CHECKED); 139 140 String title = getArguments().getString(PrintSettingsFragment.EXTRA_TITLE); 141 if (!TextUtils.isEmpty(title)) { 142 getActivity().setTitle(title); 143 } 144 } 145 146 @Override 147 public void onStart() { 148 super.onStart(); 149 updateEmptyView(); 150 updateUiForServiceState(); 151 } 152 153 @Override 154 public void onPause() { 155 if (mSearchView != null) { 156 mSearchView.setOnQueryTextListener(null); 157 } 158 super.onPause(); 159 } 160 161 @Override 162 public void onStop() { 163 super.onStop(); 164 } 165 166 @Override 167 public void onViewCreated(View view, Bundle savedInstanceState) { 168 super.onViewCreated(view, savedInstanceState); 169 initComponents(); 170 updateUiForArguments(); 171 getBackupListView().setVisibility(View.VISIBLE); 172 } 173 174 @Override 175 public void onDestroyView() { 176 if (mOldActivityTitle != null) { 177 getActivity().getActionBar().setTitle(mOldActivityTitle); 178 } 179 super.onDestroyView(); 180 mSwitchBar.removeOnSwitchChangeListener(this); 181 mSwitchBar.hide(); 182 } 183 184 private void onPreferenceToggled(String preferenceKey, boolean enabled) { 185 ((PrintManager)getContext().getSystemService(Context.PRINT_SERVICE)) 186 .setPrintServiceEnabled(mComponentName, enabled); 187 } 188 189 private ListView getBackupListView() { 190 return (ListView) getView().findViewById(R.id.backup_list); 191 } 192 193 private void updateEmptyView() { 194 ViewGroup contentRoot = (ViewGroup) getListView().getParent(); 195 View emptyView = getBackupListView().getEmptyView(); 196 if (!mToggleSwitch.isChecked()) { 197 if (emptyView != null && emptyView.getId() != R.id.empty_print_state) { 198 contentRoot.removeView(emptyView); 199 emptyView = null; 200 } 201 if (emptyView == null) { 202 emptyView = getActivity().getLayoutInflater().inflate( 203 R.layout.empty_print_state, contentRoot, false); 204 ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon); 205 iconView.setContentDescription(getString(R.string.print_service_disabled)); 206 TextView textView = (TextView) emptyView.findViewById(R.id.message); 207 textView.setText(R.string.print_service_disabled); 208 contentRoot.addView(emptyView); 209 getBackupListView().setEmptyView(emptyView); 210 } 211 } else if (mPrintersAdapter.getUnfilteredCount() <= 0) { 212 if (emptyView != null 213 && emptyView.getId() != R.id.empty_printers_list_service_enabled) { 214 contentRoot.removeView(emptyView); 215 emptyView = null; 216 } 217 if (emptyView == null) { 218 emptyView = getActivity().getLayoutInflater().inflate( 219 R.layout.empty_printers_list_service_enabled, contentRoot, false); 220 contentRoot.addView(emptyView); 221 getBackupListView().setEmptyView(emptyView); 222 } 223 } else if (mPrintersAdapter.getCount() <= 0) { 224 if (emptyView != null && emptyView.getId() != R.id.empty_print_state) { 225 contentRoot.removeView(emptyView); 226 emptyView = null; 227 } 228 if (emptyView == null) { 229 emptyView = getActivity().getLayoutInflater().inflate( 230 R.layout.empty_print_state, contentRoot, false); 231 ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon); 232 iconView.setContentDescription(getString(R.string.print_no_printers_found)); 233 TextView textView = (TextView) emptyView.findViewById(R.id.message); 234 textView.setText(R.string.print_no_printers_found); 235 contentRoot.addView(emptyView); 236 getBackupListView().setEmptyView(emptyView); 237 } 238 } 239 } 240 241 private void updateUiForServiceState() { 242 if (mServiceEnabled) { 243 mSwitchBar.setCheckedInternal(true); 244 mPrintersAdapter.enable(); 245 } else { 246 mSwitchBar.setCheckedInternal(false); 247 mPrintersAdapter.disable(); 248 } 249 getActivity().invalidateOptionsMenu(); 250 } 251 252 private void initComponents() { 253 mPrintersAdapter = new PrintersAdapter(); 254 mPrintersAdapter.registerDataSetObserver(mDataObserver); 255 256 final SettingsActivity activity = (SettingsActivity) getActivity(); 257 258 mSwitchBar = activity.getSwitchBar(); 259 mSwitchBar.addOnSwitchChangeListener(this); 260 mSwitchBar.show(); 261 262 mToggleSwitch = mSwitchBar.getSwitch(); 263 mToggleSwitch.setOnBeforeCheckedChangeListener(new ToggleSwitch.OnBeforeCheckedChangeListener() { 264 @Override 265 public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) { 266 onPreferenceToggled(mPreferenceKey, checked); 267 return false; 268 } 269 }); 270 271 getBackupListView().setSelector(new ColorDrawable(Color.TRANSPARENT)); 272 getBackupListView().setAdapter(mPrintersAdapter); 273 getBackupListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { 274 @Override 275 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 276 PrinterInfo printer = (PrinterInfo) mPrintersAdapter.getItem(position); 277 278 if (printer.getInfoIntent() != null) { 279 try { 280 getActivity().startIntentSender(printer.getInfoIntent().getIntentSender(), 281 null, 0, 0, 0); 282 } catch (SendIntentException e) { 283 Log.e(LOG_TAG, "Could not execute info intent: %s", e); 284 } 285 } 286 } 287 }); 288 } 289 290 291 @Override 292 public void onSwitchChanged(Switch switchView, boolean isChecked) { 293 updateEmptyView(); 294 } 295 296 private void updateUiForArguments() { 297 Bundle arguments = getArguments(); 298 299 // Component name. 300 mComponentName = ComponentName.unflattenFromString(arguments 301 .getString(PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME)); 302 303 // Key. 304 mPreferenceKey = mComponentName.flattenToString(); 305 306 // Enabled. 307 final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED); 308 mSwitchBar.setCheckedInternal(enabled); 309 310 getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICE_LOADER, null, this); 311 setHasOptionsMenu(true); 312 } 313 314 @Override 315 public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) { 316 return new PrintServicesLoader( 317 (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE), getContext(), 318 PrintManager.ALL_SERVICES); 319 } 320 321 @Override 322 public void onLoadFinished(Loader<List<PrintServiceInfo>> loader, 323 List<PrintServiceInfo> services) { 324 PrintServiceInfo service = null; 325 326 if (services != null) { 327 final int numServices = services.size(); 328 for (int i = 0; i < numServices; i++) { 329 if (services.get(i).getComponentName().equals(mComponentName)) { 330 service = services.get(i); 331 break; 332 } 333 } 334 } 335 336 if (service == null) { 337 // The print service was uninstalled 338 finishFragment(); 339 } 340 341 mServiceEnabled = service.isEnabled(); 342 343 if (service.getSettingsActivityName() != null) { 344 Intent settingsIntent = new Intent(Intent.ACTION_MAIN); 345 346 settingsIntent.setComponent( 347 new ComponentName(service.getComponentName().getPackageName(), 348 service.getSettingsActivityName())); 349 350 List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities( 351 settingsIntent, 0); 352 if (!resolvedActivities.isEmpty()) { 353 // The activity is a component name, therefore it is one or none. 354 if (resolvedActivities.get(0).activityInfo.exported) { 355 mSettingsIntent = settingsIntent; 356 } 357 } 358 } else { 359 mSettingsIntent = null; 360 } 361 362 if (service.getAddPrintersActivityName() != null) { 363 Intent addPrintersIntent = new Intent(Intent.ACTION_MAIN); 364 365 addPrintersIntent.setComponent( 366 new ComponentName(service.getComponentName().getPackageName(), 367 service.getAddPrintersActivityName())); 368 369 List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities( 370 addPrintersIntent, 0); 371 if (!resolvedActivities.isEmpty()) { 372 // The activity is a component name, therefore it is one or none. 373 if (resolvedActivities.get(0).activityInfo.exported) { 374 mAddPrintersIntent = addPrintersIntent; 375 } 376 } 377 } else { 378 mAddPrintersIntent = null; 379 } 380 381 updateUiForServiceState(); 382 } 383 384 @Override 385 public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) { 386 updateUiForServiceState(); 387 } 388 389 @Override 390 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 391 super.onCreateOptionsMenu(menu, inflater); 392 inflater.inflate(R.menu.print_service_settings, menu); 393 394 MenuItem addPrinters = menu.findItem(R.id.print_menu_item_add_printer); 395 if (mServiceEnabled && mAddPrintersIntent != null) { 396 addPrinters.setIntent(mAddPrintersIntent); 397 } else { 398 menu.removeItem(R.id.print_menu_item_add_printer); 399 } 400 401 MenuItem settings = menu.findItem(R.id.print_menu_item_settings); 402 if (mServiceEnabled && mSettingsIntent != null) { 403 settings.setIntent(mSettingsIntent); 404 } else { 405 menu.removeItem(R.id.print_menu_item_settings); 406 } 407 408 MenuItem searchItem = menu.findItem(R.id.print_menu_item_search); 409 if (mServiceEnabled && mPrintersAdapter.getUnfilteredCount() > 0) { 410 mSearchView = (SearchView) searchItem.getActionView(); 411 mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 412 @Override 413 public boolean onQueryTextSubmit(String query) { 414 return true; 415 } 416 417 @Override 418 public boolean onQueryTextChange(String searchString) { 419 mPrintersAdapter.getFilter().filter(searchString); 420 return true; 421 } 422 }); 423 mSearchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { 424 @Override 425 public void onViewAttachedToWindow(View view) { 426 if (AccessibilityManager.getInstance(getActivity()).isEnabled()) { 427 view.announceForAccessibility(getString( 428 R.string.print_search_box_shown_utterance)); 429 } 430 } 431 @Override 432 public void onViewDetachedFromWindow(View view) { 433 Activity activity = getActivity(); 434 if (activity != null && !activity.isFinishing() 435 && AccessibilityManager.getInstance(activity).isEnabled()) { 436 view.announceForAccessibility(getString( 437 R.string.print_search_box_hidden_utterance)); 438 } 439 } 440 }); 441 } else { 442 menu.removeItem(R.id.print_menu_item_search); 443 } 444 } 445 446 private final class PrintersAdapter extends BaseAdapter 447 implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable { 448 private final Object mLock = new Object(); 449 450 private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>(); 451 452 private final List<PrinterInfo> mFilteredPrinters = new ArrayList<PrinterInfo>(); 453 454 private CharSequence mLastSearchString; 455 456 public void enable() { 457 getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this); 458 } 459 460 public void disable() { 461 getLoaderManager().destroyLoader(LOADER_ID_PRINTERS_LOADER); 462 mPrinters.clear(); 463 } 464 465 public int getUnfilteredCount() { 466 return mPrinters.size(); 467 } 468 469 @Override 470 public Filter getFilter() { 471 return new Filter() { 472 @Override 473 protected FilterResults performFiltering(CharSequence constraint) { 474 synchronized (mLock) { 475 if (TextUtils.isEmpty(constraint)) { 476 return null; 477 } 478 FilterResults results = new FilterResults(); 479 List<PrinterInfo> filteredPrinters = new ArrayList<PrinterInfo>(); 480 String constraintLowerCase = constraint.toString().toLowerCase(); 481 final int printerCount = mPrinters.size(); 482 for (int i = 0; i < printerCount; i++) { 483 PrinterInfo printer = mPrinters.get(i); 484 String name = printer.getName(); 485 if (name != null && name.toLowerCase().contains(constraintLowerCase)) { 486 filteredPrinters.add(printer); 487 } 488 } 489 results.values = filteredPrinters; 490 results.count = filteredPrinters.size(); 491 return results; 492 } 493 } 494 495 @Override 496 @SuppressWarnings("unchecked") 497 protected void publishResults(CharSequence constraint, FilterResults results) { 498 synchronized (mLock) { 499 mLastSearchString = constraint; 500 mFilteredPrinters.clear(); 501 if (results == null) { 502 mFilteredPrinters.addAll(mPrinters); 503 } else { 504 List<PrinterInfo> printers = (List<PrinterInfo>) results.values; 505 mFilteredPrinters.addAll(printers); 506 } 507 } 508 notifyDataSetChanged(); 509 } 510 }; 511 } 512 513 @Override 514 public int getCount() { 515 synchronized (mLock) { 516 return mFilteredPrinters.size(); 517 } 518 } 519 520 @Override 521 public Object getItem(int position) { 522 synchronized (mLock) { 523 return mFilteredPrinters.get(position); 524 } 525 } 526 527 @Override 528 public long getItemId(int position) { 529 return position; 530 } 531 532 /** 533 * Checks if a printer can be used for printing 534 * 535 * @param position The position of the printer in the list 536 * @return true iff the printer can be used for printing. 537 */ 538 public boolean isActionable(int position) { 539 PrinterInfo printer = (PrinterInfo) getItem(position); 540 return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE; 541 } 542 543 @Override 544 public View getView(int position, View convertView, ViewGroup parent) { 545 if (convertView == null) { 546 convertView = getActivity().getLayoutInflater().inflate( 547 R.layout.printer_dropdown_item, parent, false); 548 } 549 550 convertView.setEnabled(isActionable(position)); 551 552 final PrinterInfo printer = (PrinterInfo) getItem(position); 553 CharSequence title = printer.getName(); 554 CharSequence subtitle = printer.getDescription(); 555 Drawable icon = printer.loadIcon(getActivity()); 556 557 TextView titleView = (TextView) convertView.findViewById(R.id.title); 558 titleView.setText(title); 559 560 TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle); 561 if (!TextUtils.isEmpty(subtitle)) { 562 subtitleView.setText(subtitle); 563 subtitleView.setVisibility(View.VISIBLE); 564 } else { 565 subtitleView.setText(null); 566 subtitleView.setVisibility(View.GONE); 567 } 568 569 LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info); 570 if (printer.getInfoIntent() != null) { 571 moreInfoView.setVisibility(View.VISIBLE); 572 moreInfoView.setOnClickListener(new OnClickListener() { 573 @Override 574 public void onClick(View v) { 575 try { 576 getActivity().startIntentSender( 577 printer.getInfoIntent().getIntentSender(), null, 0, 0, 0); 578 } catch (SendIntentException e) { 579 Log.e(LOG_TAG, "Could not execute pending info intent: %s", e); 580 } 581 } 582 }); 583 } else { 584 moreInfoView.setVisibility(View.GONE); 585 } 586 587 ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); 588 if (icon != null) { 589 iconView.setVisibility(View.VISIBLE); 590 if (!isActionable(position)) { 591 icon.mutate(); 592 593 TypedValue value = new TypedValue(); 594 getActivity().getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, 595 true); 596 icon.setAlpha((int)(value.getFloat() * 255)); 597 } 598 iconView.setImageDrawable(icon); 599 } else { 600 iconView.setVisibility(View.GONE); 601 } 602 603 return convertView; 604 } 605 606 @Override 607 public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) { 608 if (id == LOADER_ID_PRINTERS_LOADER) { 609 return new PrintersLoader(getContext()); 610 } 611 return null; 612 } 613 614 @Override 615 public void onLoadFinished(Loader<List<PrinterInfo>> loader, 616 List<PrinterInfo> printers) { 617 synchronized (mLock) { 618 mPrinters.clear(); 619 final int printerCount = printers.size(); 620 for (int i = 0; i < printerCount; i++) { 621 PrinterInfo printer = printers.get(i); 622 if (printer.getId().getServiceName().equals(mComponentName)) { 623 mPrinters.add(printer); 624 } 625 } 626 mFilteredPrinters.clear(); 627 mFilteredPrinters.addAll(mPrinters); 628 if (!TextUtils.isEmpty(mLastSearchString)) { 629 getFilter().filter(mLastSearchString); 630 } 631 } 632 notifyDataSetChanged(); 633 } 634 635 @Override 636 public void onLoaderReset(Loader<List<PrinterInfo>> loader) { 637 synchronized (mLock) { 638 mPrinters.clear(); 639 mFilteredPrinters.clear(); 640 mLastSearchString = null; 641 } 642 notifyDataSetInvalidated(); 643 } 644 } 645 646 private static class PrintersLoader extends Loader<List<PrinterInfo>> { 647 648 private static final String LOG_TAG = "PrintersLoader"; 649 650 private static final boolean DEBUG = false; 651 652 private final Map<PrinterId, PrinterInfo> mPrinters = 653 new LinkedHashMap<PrinterId, PrinterInfo>(); 654 655 private PrinterDiscoverySession mDiscoverySession; 656 657 public PrintersLoader(Context context) { 658 super(context); 659 } 660 661 @Override 662 public void deliverResult(List<PrinterInfo> printers) { 663 if (isStarted()) { 664 super.deliverResult(printers); 665 } 666 } 667 668 @Override 669 protected void onStartLoading() { 670 if (DEBUG) { 671 Log.i(LOG_TAG, "onStartLoading()"); 672 } 673 // The contract is that if we already have a valid, 674 // result the we have to deliver it immediately. 675 if (!mPrinters.isEmpty()) { 676 deliverResult(new ArrayList<PrinterInfo>(mPrinters.values())); 677 } 678 // We want to start discovery at this point. 679 onForceLoad(); 680 } 681 682 @Override 683 protected void onStopLoading() { 684 if (DEBUG) { 685 Log.i(LOG_TAG, "onStopLoading()"); 686 } 687 onCancelLoad(); 688 } 689 690 @Override 691 protected void onForceLoad() { 692 if (DEBUG) { 693 Log.i(LOG_TAG, "onForceLoad()"); 694 } 695 loadInternal(); 696 } 697 698 @Override 699 protected boolean onCancelLoad() { 700 if (DEBUG) { 701 Log.i(LOG_TAG, "onCancelLoad()"); 702 } 703 return cancelInternal(); 704 } 705 706 @Override 707 protected void onReset() { 708 if (DEBUG) { 709 Log.i(LOG_TAG, "onReset()"); 710 } 711 onStopLoading(); 712 mPrinters.clear(); 713 if (mDiscoverySession != null) { 714 mDiscoverySession.destroy(); 715 mDiscoverySession = null; 716 } 717 } 718 719 @Override 720 protected void onAbandon() { 721 if (DEBUG) { 722 Log.i(LOG_TAG, "onAbandon()"); 723 } 724 onStopLoading(); 725 } 726 727 private boolean cancelInternal() { 728 if (mDiscoverySession != null 729 && mDiscoverySession.isPrinterDiscoveryStarted()) { 730 mDiscoverySession.stopPrinterDiscovery(); 731 return true; 732 } 733 return false; 734 } 735 736 private void loadInternal() { 737 if (mDiscoverySession == null) { 738 PrintManager printManager = (PrintManager) getContext() 739 .getSystemService(Context.PRINT_SERVICE); 740 mDiscoverySession = printManager.createPrinterDiscoverySession(); 741 mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() { 742 @Override 743 public void onPrintersChanged() { 744 deliverResult(new ArrayList<PrinterInfo>( 745 mDiscoverySession.getPrinters())); 746 } 747 }); 748 } 749 mDiscoverySession.startPrinterDiscovery(null); 750 } 751 } 752 } 753