From c8d6f54be3c05d13c63d2eb353eef9c24964630c Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Thu, 6 Oct 2016 10:21:50 -0700 Subject: [PATCH] Allow to select printer from info activity. Test: Manual testing with modified experimental print service and new CTS test for the new API Fixes: 27746841 Change-Id: I4ef728e54679271a01397d9f04d3b8ac804ffcf3 --- api/current.txt | 2 + api/system-current.txt | 2 + api/test-current.txt | 2 + .../android/printservice/PrintService.java | 23 ++++++ .../ui/SelectPrinterActivity.java | 74 ++++++++++++++++--- 5 files changed, 94 insertions(+), 9 deletions(-) diff --git a/api/current.txt b/api/current.txt index 9f5a8e28aa638..558deb8521a16 100644 --- a/api/current.txt +++ b/api/current.txt @@ -30463,9 +30463,11 @@ package android.printservice { method protected void onDisconnected(); method protected abstract void onPrintJobQueued(android.printservice.PrintJob); method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob); + field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER"; field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO"; field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO"; field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO"; + field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER"; field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService"; field public static final java.lang.String SERVICE_META_DATA = "android.printservice"; } diff --git a/api/system-current.txt b/api/system-current.txt index 4d7c4af950fff..eaf9947ba5ba5 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -33063,9 +33063,11 @@ package android.printservice { method protected void onDisconnected(); method protected abstract void onPrintJobQueued(android.printservice.PrintJob); method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob); + field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER"; field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO"; field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO"; field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO"; + field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER"; field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService"; field public static final java.lang.String SERVICE_META_DATA = "android.printservice"; } diff --git a/api/test-current.txt b/api/test-current.txt index 4be2e7f475737..edb634edac2cf 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -30541,9 +30541,11 @@ package android.printservice { method protected void onDisconnected(); method protected abstract void onPrintJobQueued(android.printservice.PrintJob); method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob); + field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER"; field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO"; field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO"; field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO"; + field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER"; field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService"; field public static final java.lang.String SERVICE_META_DATA = "android.printservice"; } diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java index 8f73518eba0fd..ecf17707a5c84 100644 --- a/core/java/android/printservice/PrintService.java +++ b/core/java/android/printservice/PrintService.java @@ -18,6 +18,8 @@ package android.printservice; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.Activity; +import android.app.PendingIntent; import android.app.Service; import android.content.ComponentName; import android.content.Context; @@ -29,6 +31,7 @@ import android.os.Message; import android.os.RemoteException; import android.print.PrintJobInfo; import android.print.PrinterId; +import android.print.PrinterInfo; import android.util.Log; import com.android.internal.util.Preconditions; @@ -247,6 +250,26 @@ public abstract class PrintService extends Service { public static final String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO"; + /** + * When the {@link PendingIntent} declared via + * {@link PrinterInfo.Builder#setInfoIntent(PendingIntent)} is called this boolean extra + * will be filled in if the activity can select the printer. + * + * @see #EXTRA_SELECT_PRINTER + */ + public static final String EXTRA_CAN_SELECT_PRINTER = + "android.printservice.extra.CAN_SELECT_PRINTER"; + + /** + * If this boolean extra is set to {@code true} in the {@link Activity#setResult(int, Intent) + * result data} from the activity specified in + * {@link PrinterInfo.Builder#setInfoIntent(PendingIntent)} the printer will be selected. + * + * @see #EXTRA_CAN_SELECT_PRINTER + */ + public static final String EXTRA_SELECT_PRINTER = + "android.printservice.extra.SELECT_PRINTER"; + private Handler mHandler; private IPrintServiceClient mClient; diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java index cc6908942a0ea..293665a208ba6 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java @@ -17,6 +17,7 @@ package com.android.printspooler.ui; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Activity; import android.app.LoaderManager; import android.content.ComponentName; @@ -24,13 +25,17 @@ import android.content.Context; import android.content.Intent; import android.content.IntentSender.SendIntentException; import android.content.Loader; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.database.DataSetObserver; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.print.PrintManager; import android.print.PrintServicesLoader; import android.print.PrinterId; import android.print.PrinterInfo; +import android.printservice.PrintService; import android.printservice.PrintServiceInfo; import android.provider.Settings; import android.text.TextUtils; @@ -76,6 +81,8 @@ public final class SelectPrinterActivity extends Activity implements private static final int LOADER_ID_PRINT_REGISTRY_INT = 2; private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 3; + private static final int INFO_INTENT_REQUEST_CODE = 1; + public static final String INTENT_EXTRA_PRINTER = "INTENT_EXTRA_PRINTER"; private static final String EXTRA_PRINTER = "EXTRA_PRINTER"; @@ -83,6 +90,7 @@ public final class SelectPrinterActivity extends Activity implements private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE"; private static final String KEY_DID_SEARCH = "DID_SEARCH"; + private static final String KEY_PRINTER_FOR_INFO_INTENT = "KEY_PRINTER_FOR_INFO_INTENT"; // Constants for MetricsLogger.count and MetricsLogger.histo private static final String PRINTERS_LISTED_COUNT = "printers_listed"; @@ -100,6 +108,12 @@ public final class SelectPrinterActivity extends Activity implements private boolean mDidSearch; + /** + * Printer we are currently in the info intent for. This is only non-null while this activity + * started an info intent that has not yet returned + */ + private @Nullable PrinterInfo mPrinterForInfoIntent; + private void startAddPrinterActivity() { MetricsLogger.action(this, MetricsEvent.ACTION_PRINT_SERVICE_ADD); startActivity(new Intent(this, AddPrinterActivity.class)); @@ -200,6 +214,7 @@ public final class SelectPrinterActivity extends Activity implements if (savedInstanceState != null) { mDidSearch = savedInstanceState.getBoolean(KEY_DID_SEARCH); + mPrinterForInfoIntent = savedInstanceState.getParcelable(KEY_PRINTER_FOR_INFO_INTENT); } } @@ -208,6 +223,7 @@ public final class SelectPrinterActivity extends Activity implements super.onSaveInstanceState(outState); outState.putBoolean(KEY_NOT_FIRST_CREATE, true); outState.putBoolean(KEY_DID_SEARCH, mDidSearch); + outState.putParcelable(KEY_PRINTER_FOR_INFO_INTENT, mPrinterForInfoIntent); } @Override @@ -353,6 +369,24 @@ public final class SelectPrinterActivity extends Activity implements super.onDestroy(); } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case INFO_INTENT_REQUEST_CODE: + if (resultCode == RESULT_OK && + data != null && + data.getBooleanExtra(PrintService.EXTRA_SELECT_PRINTER, false) && + mPrinterForInfoIntent != null && + mPrinterForInfoIntent.getStatus() != PrinterInfo.STATUS_UNAVAILABLE) { + onPrinterSelected(mPrinterForInfoIntent); + } + mPrinterForInfoIntent = null; + break; + default: + // not reached + } + } + private void onPrinterSelected(PrinterInfo printer) { Intent intent = new Intent(); intent.putExtra(INTENT_EXTRA_PRINTER, printer); @@ -418,6 +452,26 @@ public final class SelectPrinterActivity extends Activity implements } } + /** + * Return the target SDK of the package that defined the printer. + * + * @param printer The printer + * + * @return The target SDK that defined a printer. + */ + private int getTargetSDKOfPrintersService(@NonNull PrinterInfo printer) { + ApplicationInfo serviceAppInfo; + try { + serviceAppInfo = getPackageManager().getApplicationInfo( + printer.getId().getServiceName().getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOG_TAG, "Could not find package that defined the printer", e); + return Build.VERSION_CODES.KITKAT; + } + + return serviceAppInfo.targetSdkVersion; + } + private final class DestinationAdapter extends BaseAdapter implements Filterable { private final Object mLock = new Object(); @@ -638,15 +692,17 @@ public final class SelectPrinterActivity extends Activity implements LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info); if (printer.getInfoIntent() != null) { moreInfoView.setVisibility(View.VISIBLE); - moreInfoView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - try { - startIntentSender(printer.getInfoIntent().getIntentSender(), null, 0, 0, - 0); - } catch (SendIntentException e) { - Log.e(LOG_TAG, "Could not execute pending info intent: %s", e); - } + moreInfoView.setOnClickListener(v -> { + Intent fillInIntent = new Intent(); + fillInIntent.putExtra(PrintService.EXTRA_CAN_SELECT_PRINTER, true); + + try { + mPrinterForInfoIntent = printer; + startIntentSenderForResult(printer.getInfoIntent().getIntentSender(), + INFO_INTENT_REQUEST_CODE, fillInIntent, 0, 0, 0); + } catch (SendIntentException e) { + mPrinterForInfoIntent = null; + Log.e(LOG_TAG, "Could not execute pending info intent: %s", e); } }); } else {