Google 云打印:读取 属性 'o' 的 null

Google Cloud Printing: read property 'o' of null

我在使用 Google 单击打印按钮时使用云打印时遇到问题。

调试模式下的错误显示

Uncaught TypeError: Cannot read property 'o' of null", source: https://www.google.com/cloudprint/client/2026774633-dialog_mobile__vi.js (295)

有人解决这个问题吗?

编辑 1

这是我 class PrintDialogActivity.java

的代码
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.Bundle;
import android.util.Base64;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

@SuppressLint("SetJavaScriptEnabled") 
public class PrintDialogActivity extends Activity {
  private static final String PRINT_DIALOG_URL = "https://www.google.com/cloudprint/dialog.html";
  private static final String JS_INTERFACE = "AndroidPrintDialog";
  private static final String CONTENT_TRANSFER_ENCODING = "base64";

  private static final String ZXING_URL = "http://zxing.appspot.com";
  private static final int ZXING_SCAN_REQUEST = 65743;

  /**
   * Post message that is sent by Print Dialog web page when the printing dialog
   * needs to be closed.
   */
  private static final String CLOSE_POST_MESSAGE_NAME = "cp-dialog-on-close";

  /**
   * Web view element to show the printing dialog in.
   */
  private WebView dialogWebView;

  /**
   * Intent that started the action.
   */
  Intent cloudPrintIntent;

  @SuppressLint("JavascriptInterface") @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    setContentView(R.layout.print_dialog);
    dialogWebView = (WebView) findViewById(R.id.webview);
    cloudPrintIntent = this.getIntent();

    WebSettings settings = dialogWebView.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
    dialogWebView.setWebViewClient(new PrintDialogWebClient());
    dialogWebView.addJavascriptInterface(
      new PrintDialogJavaScriptInterface(), JS_INTERFACE);

    dialogWebView.loadUrl(PRINT_DIALOG_URL);
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == ZXING_SCAN_REQUEST && resultCode == RESULT_OK) {
      dialogWebView.loadUrl(intent.getStringExtra("SCAN_RESULT"));
    }
  }

  final class PrintDialogJavaScriptInterface {
    public String getType() {
      return cloudPrintIntent.getType();
    }

    public String getTitle() {
      return cloudPrintIntent.getExtras().getString("title");
    }

    public String getContent() {
      try {
        ContentResolver contentResolver = getContentResolver();
        InputStream is = contentResolver.openInputStream(cloudPrintIntent.getData());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer = new byte[4096];
        int n = is.read(buffer);
        while (n >= 0) {
          baos.write(buffer, 0, n);
          n = is.read(buffer);
        }
        is.close();
        baos.flush();

        return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return "";
    }

    public String getEncoding() {
      return CONTENT_TRANSFER_ENCODING;
    }

    public void onPostMessage(String message) {
      if (message.startsWith(CLOSE_POST_MESSAGE_NAME)) {
        finish();
      }
    }
  }

  private final class PrintDialogWebClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      if (url.startsWith(ZXING_URL)) {
        Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
        intentScan.putExtra("SCAN_MODE", "QR_CODE_MODE");
        try {
          startActivityForResult(intentScan, ZXING_SCAN_REQUEST);
        } catch (ActivityNotFoundException error) {
          view.loadUrl(url);
        }
      } else {
        view.loadUrl(url);
      }
      return false;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
      if (PRINT_DIALOG_URL.equals(url)) {
        // Submit print document.
        view.loadUrl("javascript:printDialog.setPrintDocument(printDialog.createPrintDocument("
          + "window." + JS_INTERFACE + ".getType(),window." + JS_INTERFACE + ".getTitle(),"
          + "window." + JS_INTERFACE + ".getContent(),window." + JS_INTERFACE + ".getEncoding()))");

        // Add post messages listener.
        view.loadUrl("javascript:window.addEventListener('message',"
            + "function(evt){window." + JS_INTERFACE + ".onPostMessage(evt.data)}, false)");
      }
    }
  }
}

现在,我找到了解决问题的方法: 可能问题来自 Android SDK 版本。你可以看到这个link:https://developers.google.com/cloud-print/docs/android。 (这意味着 GCP 仅支持下面的 Android 版本 4.3)。 虽然,我在模拟器4.2上测试过,但还是不走运。

所以,我把方向改成了Android Print Framework 有点吃力

首先,我必须在模拟器上安装云打印服务。

其次,我登录Google启用打印功能的帐户服务并连接到我的打印机。

第三,我使用这段代码执行打印操作

private void printDoc() {
        PrintManager printManager = (PrintManager) this.getSystemService(Context.PRINT_SERVICE);
        String jobName = mFileName;


        Intent myIntent = getIntent();
        Uri docUri = myIntent != null ? myIntent.getData() : null;

        PrintDocumentAdapter pda = new PrintDocumentAdapter(){
            @Override
            public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras){

                if (cancellationSignal.isCanceled()) {
                    callback.onLayoutCancelled();
                    //return;
                }

             // Compute the expected number of printed pages
                int pages = computePageCount(newAttributes);

                PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(mFileName).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(pages).build();

                callback.onLayoutFinished(pdi, true);
            }

            @Override
            public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback){
                InputStream input = null;
                OutputStream output = null;

                try {

                    input = new FileInputStream(docUri.toString());
                    output = new FileOutputStream(destination.getFileDescriptor());

                    byte[] buf = new byte[1024];
                    int bytesRead;

                    while ((bytesRead = input.read(buf)) > 0) {
                         output.write(buf, 0, bytesRead);
                    }

                    callback.onWriteFinished(pages);

                } catch (FileNotFoundException ee){
                    //Catch exception
                } catch (Exception e) {
                    //Catch exception
                } finally {
                    try {
                        input.close();
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }


        };
        printManager.print(jobName, pda, null);
    }