If you’ve worked with Google Cloud Printing then you know that much of the sample code out there that shows how to submit print jobs using Java or C# don’t work … frustrating to say the least.
After more pain then I’d care to admit, I finally got the code working so wanted to share it.
Below is the code to submit a PDF file for Printing (or storage on a Google Drive) using Google Cloud Printing from an Android device.
For a complete Android Studio project that shows how to interrogate the available printers, get the list of print jobs, and submit a print job download this project zip file.
public class GoogleCloudPrint { private static final String SERVICE_SOURCE_NAME = "your-apps-name-for-logging-purposes"; public static final String GCP_BASE_URL_STRING = "https://www.google.com/cloudprint"; private static final String SUBMIT_URL_STRING = GCP_BASE_URL_STRING + "/submit"; private static final int DEFAULT_STREAMING_CHUNK_SIZE = 0; String mUsername; String mPassword; public GoogleCloudPrint(String username, String password) { mUsername = username; mPassword = password; } public void print(String printerId, String title, File documentFile, String mimeType) { try { byte[] documentBytes = getBytes(documentFile); String urlString = SUBMIT_URL_STRING + "?output=json" + "&printerid=" + printerId + "&contentType=" + mimeType + "&title=" + title ; // Open connection and configure for POST with streaming writes HttpsURLConnection connection = createConnection(urlString); connection.setDoOutput(true); connection.setChunkedStreamingMode(DEFAULT_STREAMING_CHUNK_SIZE); // Create the multi-part form data prefix and suffix // include filename value in prefix String queryPrefix = String.format( "------CloudPrintFormBoundaryqeq6g6ncj5v7\r\n" + "Content-Disposition: form-data; name=\"content\"; filename=\"%s\"\r\n" + "\r\n", title); String querySuffix = "\r\n------CloudPrintFormBoundaryqeq6g6ncj5v7--"; // Encoide prefix and suffix and determine total content length byte[] queryPrefixBytes = EncodingUtils.getAsciiBytes(queryPrefix); byte[] querySuffixBytes = EncodingUtils.getAsciiBytes(querySuffix); int contentLength = queryPrefixBytes.length + documentBytes.length + querySuffixBytes.length; // Add headers for multipart form data and length connection.addRequestProperty("Content-Type", "multipart/form-data; boundary=----CloudPrintFormBoundaryqeq6g6ncj5v7"); connection.addRequestProperty("Content-Length", Integer.toString(contentLength)); // Write the document to server wrapped as multipart form data writePrintBody(connection, queryPrefixBytes, documentBytes, querySuffixBytes); // Write results to log InputStream inStream = connection.getInputStream(); } catch (Exception e) { e.printStackTrace(); } } private HttpsURLConnection createConnection(String urlString) throws IOException { String auth = retrieveAuthToken(mUsername, mPassword); URL url = new URL(urlString); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.addRequestProperty("X-CloudPrint-Proxy", SERVICE_SOURCE_NAME); connection.addRequestProperty("Authorization", "GoogleLogin auth=" + auth); return connection; } private void writePrintBody(HttpsURLConnection connection, byte[] prefixBytes, byte[] documentByes, byte[] suffixBytes) throws IOException { OutputStream outStream = new BufferedOutputStream(connection.getOutputStream()); outStream.write(prefixBytes, 0, prefixBytes.length); outStream.write(documentByes, 0, documentByes.length); outStream.write(suffixBytes, 0, suffixBytes.length); outStream.flush(); outStream.close(); } private String retrieveAuthToken(String userId, String password) { final String AUTHORIZE_URL_FORMAT = "https://www.google.com/accounts/ClientLogin" + "?accountType=HOSTED_OR_GOOGLE" + "&Email=%s" + "&Passwd=%s" + "&service=cloudprint" + "&source=" + SERVICE_SOURCE_NAME; String authorizeURL = String.format(AUTHORIZE_URL_FORMAT, userId, password); String auth = "NOT_SET"; InputStream inStream = null; BufferedReader reader = null; try { URL url = new URL(authorizeURL); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); inStream = connection.getInputStream(); reader = new BufferedReader(new InputStreamReader(inStream)); String buffer; StringBuilder stringBuilder = new StringBuilder(); while ((buffer = reader.readLine()) != null) { String[] parts = buffer.split("="); if ("Auth".equalsIgnoreCase(parts[0])) { auth = parts[1]; break; } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (reader != null) reader.close(); if (inStream != null) inStream.close(); } catch (Exception e) { e.printStackTrace(); } } return auth; } private byte[] getBytes(File documentFile) { byte[] bytes = null; try { FileInputStream inputStream = new FileInputStream(documentFile); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int n = inputStream.read(buffer); while (n >= 0) { baos.write(buffer, 0, n); n = inputStream.read(buffer); } inputStream.close(); baos.flush(); bytes = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return bytes; } }
Thank you for your sharing!:)
Is there any method that we can send orientation potrait/landscape to the printer or a dimension?