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