如何在Android应用中指定和添加自定义打印机? [英] How do I specify and add a custom printer in an Android app?

查看:1503
本文介绍了如何在Android应用中指定和添加自定义打印机?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Android创建一款应用。所需的应用程序功能的一部分是用户可以选择一个特殊的打印机(我们只称它为传输打印机),它将把待打印的文件传递给在外部服务器上运行的进程。

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.

我需要采取哪些步骤将自定义打印机添加到Android打印面板中的打印机列表中,可以从溢出菜单的打印选项访问?

由于用户体验的考虑,最好使用现有的Android打印面板功能,而不是应用程序选择器中的附加共享选项;用户单击共享而不是打印以获得所需功能将不会直观。

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.

有一个现有的类似问题,因为它没有引起人们的兴趣发布前一段时间。提问者已将PrintManager类确定为领导,但我相信 PrintService 类可能更富有成效:

There is an existing similar question which has gathered little interest since it was posted some time ago. The asker has identified the PrintManager class as a lead but I believe that the PrintService class is likely to be more 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 done so as below.

在AndroidManifest.xml中:

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>



元数据



目前还不清楚我确切地指定了元数据的位置。从PrintService页面的SERVICE_META_DATA部分:

Meta-data

It's unclear to me exactly where the meta-data is supposed to be specified. From SERVICE_META_DATA section of the PrintService page:


此元数据必须引用包含打印服务标签的XML资源。

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

在res / xml / transfer_print_service.xml中:

In res/xml/transfer_print_service.xml:

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



TransferPrintService Class



这会创建一个自定义PrinterDiscoverySession。我在这个阶段的目标是让打印机出现在打印面板上并从那里开始工作。

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) {
    }
}

该服务在一个ACTION_BOOT_COMPLETED意图的BroadcastReceiver中启动。

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

这实际上创建了自定义打印机。

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() {
    }
}



主要问题




  • 这不会产生额外的打印机选项。

  • 文件的排列是否正确?具体来说,在res下的单独XML文档中使用< print-service> 标记?尝试将标记放在AndroidManfiest.xml文档中的任何位置会产生IDE错误。

  • 如何调用TransferPrintService?例如,假设我在Chrome中,我打开Overflow菜单,然后选择Print ...调用哪个PrintService?我如何确定它是我的?

  • 我在这里走错了轨道吗?

  • Major Concerns

    • This doesn't produce an additional printer option.
    • Is the arrangement of documents correct? Specifically, having the <print-service> tag in a separate XML document under res? Trying to place the tag anywhere in the AndroidManfiest.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?
    • 推荐答案

      我缺少的技巧实际上是通过Android设置菜单启用打印服务。实际上这样做并不像我希望的那样简单,因为设备制造商已经从菜单中删除了设置。它应该在菜单的系统部分的辅助功能下。

      The trick I was missing was actually enabling the Print Service via the Android Settings menu. Actually doing this wasn't as straightforward as I would have hoped as the device manufacturer had removed the setting from the menu. It should be right under Accessibility in the System section of the menu.

      我最终安装了Google的云端打印应用程序,这使我可以暂时访问打印服务设置(启用云打印服务)。一旦到了这里,我注意到我自己的服务实际上已经存在。

      I ended up installing the Cloud Print app by Google, which gave me access to the Print Service settings temporarily (to enable the Cloud Print service). Once in here I noticed that my own service was, in fact, present.

      对于后代:为了避免每次你想要的时候不安装和重新安装云打印更改打印服务设置,使用以下SQLite3命令,使用adb shell或从终端仿真器(或类似):

      For posterity: To avoid un-installing and re-installing Cloud Print every time you want to change the Print Service settings, use the following SQLite3 commands, either with adb shell or from Terminal Emulator (or similar):

      sqlite3 data/data/com.android.providers.settings/databases/settings.db
      

      你现在应该有访问Settings数据库并使用SQLite3命令行shell。感兴趣的设置位于安全表中,并且 enabled_print_services enabled_on_first_boot_system_print_services 。您可以使用以下方法检查这些设置是否已存在:

      You should now have access to the Settings database and be using the SQLite3 command line shell. The settings of interest are located in the secure table and are enabled_print_services and enabled_on_first_boot_system_print_services. You can check if these settings already exist by using:

      .dump secure
      

      如果没有,请使用以下命令:

      If they don't, then use the following commands:

      INSERT INTO secure VALUES(<id>, 'enabled_on_first_boot_system_print_services', 'com.companyname.appservice/com.companyname.appservice.TransferPrintService');
      INSERT INTO secure VALUES(<id>, 'enabled_print_services', 'com.companyname.appservice/com.companyname.appservice.TransferPrintService');
      

      当然,你应该用你自己的包和'TransferPrintService'替换'com.companyname.appservice' '有自己的打印服务。如果这些设置名称已经存在,并且您的打印服务未列出,则您需要更新而不是INSERT INTO:

      You should, of course, replace 'com.companyname.appservice' with your own package and 'TransferPrintService' with your own print service. If these setting names do already exist, and your print service isn't listed, then you'll need to UPDATE instead of INSERT INTO:

      UPDATE secure SET value = '<existing print services>:<new print service>' WHERE name = 'enabled_on_first_boot_system_print_services';
      UPDATE secure SET value = '<existing print services>:<new print service>' WHERE name = 'enabled_print_services';
      

      您需要确保在UPDATE命令中包含任何现有的打印服务;列出的打印服务用冒号:分隔。

      You'll need to make sure to include any existing print services as part of the UPDATE command; listed print services are separated by a colon ":".

      重新启动设备以将更新应用到设置数据库。

      Reboot the device to apply the updates to the settings database.

      这篇关于如何在Android应用中指定和添加自定义打印机?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆