I'm creating an app for Android. Part of the desired app functionality is 
that the user can select a special printer (let's just call it Transfer 
Printer) which will pass on the document-to-be-printed to a process running 
on an external server.

*What steps do I need to take to add a custom printer to the list of 
printers in the Android print panel, accessible from the Print option of 
the Overflow menu?*

It is desirable to use the existing Android print panel functionality 
rather than, for example, an additional Share option in the App Selector 
because of user experience considerations; it won't be intuitive to the 
user to click Share rather than Print for the desired functionality.

I think the PrintService 
<http://developer.android.com/reference/android/printservice/PrintService.html> 
class is likely to prove fruitful:

A print service is responsible for discovering printers, adding discovered 
> printers, removing added printers, and updating added printers.
>

The same page details Declaration and Configuration of the print service. 
I've tried this as shown below.


*Declaration and Configuration*

In AndroidManifest.xml:

...
<application
    ... >
    ...
    <service
        android:name=".TransferPrintService"
        android:permission="android.permission.BIND_PRINT_SERVICE"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.printservice.PrintService" />
        </intent-filter>
        <meta-data
            android:name="android.printservice"
            android:resource="@xml/transfer_print_service" />
    </service>
</application>


*Meta-data*

It's unclear to me exactly where the meta-data is supposed to be specified. 
>From the SERVICE_META_DATA sectio 
<http://developer.android.com/reference/android/printservice/PrintService.html#SERVICE_META_DATA>n
 
of the PrintService page on the Android Developer site:

This meta-data must reference a XML resource containing a print-service tag.
>

I created a new document, res/xml/transfer_print_service.xml:

<print-service
    android:label="TransferPrintService"
    android:vendor="Company Ltd." />


*TransferPrintService Class*

This creates a custom PrinterDiscoverySession. My goal at this stage is to 
just get a printer appearing in the print panel and work from there.

public class TransferPrintService extends PrintService {

    public TransferPrintService() {
    }

    @Override
    public void onPrintJobQueued(PrintJob printJob) {
        printJob.start();
        printJob.complete();
    }

    @Override
    public PrinterDiscoverySession onCreatePrinterDiscoverySession() {
        return new TransferPrinterDiscoverySession(this);
    }

    @Override
    public void onRequestCancelPrintJob(PrintJob printJob) {
    }
}

The service is started in a BroadcastReceiver on an ACTION_BOOT_COMPLETED 
intent.

*TransferPrinterDiscoverySession Class*

This actually creates the custom printer.

public class TransferPrinterDiscoverySession extends 
PrinterDiscoverySession {
    private transferPrintService printService;
    private static final String PRINTER = "Transfer Printer";

    public transferPrinterDiscoverySession(TransferPrintService 
printService) {
        this.printService = printService;
    }

    @Override
    public void onStartPrinterDiscovery(List<PrinterId> printerList) {
        PrinterId id = printService.generatePrinterId(PRINTER);
        PrinterInfo.Builder builder =
                new PrinterInfo.Builder(id, PRINTER, 
PrinterInfo.STATUS_IDLE);
        PrinterInfo info = builder.build();
        List<PrinterInfo> infos = new ArrayList<>();
        infos.add(info);
        addPrinters(infos);
    }

    @Override
    public void onStopPrinterDiscovery() {
    }

    @Override
    public void onValidatePrinters(List<PrinterId> printerIds) {
    }

    @Override
    public void onStartPrinterStateTracking(PrinterId printerId) {
        PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId,
                PRINTER, PrinterInfo.STATUS_IDLE);
        PrinterCapabilitiesInfo.Builder capBuilder =
                new PrinterCapabilitiesInfo.Builder(printerId);

        capBuilder.addMediaSize(PrintAttributes.MediaSize.ISO_A4, true);
        capBuilder.addResolution(new PrintAttributes.Resolution(
                "Default", "Default", 360, 360), true);
        capBuilder.setColorModes(PrintAttributes.COLOR_MODE_COLOR
                + PrintAttributes.COLOR_MODE_MONOCHROME,
                PrintAttributes.COLOR_MODE_COLOR);
        capBuilder.setMinMargins(PrintAttributes.Margins.NO_MARGINS);

        PrinterCapabilitiesInfo caps = capBuilder.build();
        builder.setCapabilities(caps);
        PrinterInfo info = builder.build();
        List<PrinterInfo> infos = new ArrayList<PrinterInfo>();
        infos.add(info);
        addPrinters(infos);
    }

    @Override
    public void onStopPrinterStateTracking(PrinterId printerId) {
    }

    @Override
    public void onDestroy() {
    }
}


*Concerns and Outstanding Questions*


   - This doesn't produce an additional printer option.
   - Is the arrangement of documents correct? Specifically, should I have 
   the <printer-service> tag in a separate XML document under res, as I have 
   done? Trying to place the tag elsewhere in the AndroidManifest.xml document 
   produces IDE errors.
   - How do I call into the TransferPrintService? As an example, suppose 
   I'm in Chrome, I open the Overflow menu, and select Print... Which 
   PrintService is invoked? How do I make sure it's mine?
   - Am I on completely the wrong track here?

-- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/android-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/android-developers/6599495c-ba92-43e0-a6fb-101b121515cc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to