Search code examples
javaandroidgoogle-cloud-print

Android Google CloudPrint Submit a PDF print job via URL API


Im having trouble getting the correct code to send submit a multipart form with a PDF included to google cloud print( the reason I'm not using the inbuilt intent in android is that you cant automatically select a printer it need to be done manually when using the intent)

I have been using Volley to submit it but I have been reading its not great with large files?

 final RequestQueue queue =       Volley1.getInstance(this).getRequestQueue();
            String url3 = "https://www.google.com/cloudprint/submit";
            final VolleyMultipartRequest multipartRequest = new       VolleyMultipartRequest(Request.Method.POST, url3 ,new             Response.Listener<NetworkResponse>() {

                    @Override
                    public void onResponse(NetworkResponse response) {
                            String resultResponse = new             String(response.data);
                            Log.d("responseis",resultResponse);
                    }
            }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                            error.printStackTrace();
                    }
            }){
                    @Override
                    protected Map<String, String> getParams() {

                            Map<String, String>  params = new HashMap<>();
                            // the POST parameters:
                            params.put("redirect_uri", "xxxxx");
                            params.put("printerid","xxxxxx");
                            params.put("title", "result1.pdf");
                            params.put("contentType", "application/pdf");
                            params.put("ticket", "{\"print\":{},\"version\":\"1.0\"}");
                            params.put("hl", "en");
                            return params;
                    }
                    @Override
                    public Map getHeaders() throws AuthFailureError {
                            Map headers = new HashMap();
                            headers.put("Authorization", "OAuth"+" "+res);
                            headers.put("Content-Type", "multipart/form-data; boundary=__1466595844361__");
                            //headers.put("Content-Type","application/x-www-form-urlencoded");
                            //Logger.debugE(Constants.accesstoken, headers.toString());
                            return headers;
                    }
                    @Override
                    protected Map<String, DataPart> getByteData() {
                            Map<String, DataPart> params = new HashMap<>();
                            //String yourFilePath =       Environment.getExternalStorageDirectory().getAbsolutePath()+ "/PDFs/result1.pdf";
                            String yourFilePath=Environment.getExternalStorageDirectory().getAbsolutePath()+ "/PDFs/result1.pdf";
                            File dir = new File(Environment.getExternalStoragePublicDirectory(
                                    Environment.DIRECTORY_DOWNLOADS), "PDF_reader");

                            File text = new File(dir + File.separator +  "test_r.pdf");
                            String input = text.getAbsolutePath();
                            byte[] data = new byte[(int) input.length()];
                            try {
                                    //convert file into array of bytes
                                     data = FileUtils.readFileToByteArray(text);

                            }catch(Exception e){
                                    e.printStackTrace();
                            }

                            params.put("content", new DataPart("result1.pdf",data , "application/pdf"));
                            return params;
                    }
            };
 queue.add(multipartrequest);

Solution

  • After a lot of trial and error I ended up using OKHTTP library and I was successfully able to submit a print job to google cloud print using the API. It was a bit tricky to get the multipart form with the pdf file included but the correct working request is below. Obviously the token and printerid are retrieved in other requests and need to be added manually.

    public void run() throws Exception {
    
    //File directory
    File dir = Environment.getExternalStorageDirectory();
    File file = new File(dir, "PDFs/result1.pdf");
    if(file.canRead()){
        Log.d("file", "can read");
    }else {Log.d("file","cant read");};
    
    
    // Final request body
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("content","result1.pdf",RequestBody.create(MediaType.parse("application/pdf"), file))
            .build();
    
    //URL Parameters
    HttpUrl url = new HttpUrl.Builder()
            .scheme("https")
            .host("www.google.com")
            .addPathSegments("cloudprint/submit")
            .addQueryParameter("printerid", "82d70sde-694b-3385-f263-164cb04320c3")
            .build();
    
    Request request = new Request.Builder()
            .header("Authorization", "OAuth ya29.Cl0jAxDuQni_Dskz6Y2r-wRaJVMxEw8fy5hPNfAm02pDLnZc9HX-RfHpmMoS0OL-Wv_SKxBtYIwRK9jVpJDwl7Qs-RFt02Qc5Yoid4w1kV8b4vBIpcleIQ8lBEto")
            .url(url)
            .post(requestBody)
            .build();
    
    client.newCall(request)
            .enqueue(new Callback() {
                @Override
                public void onFailure(final Call call, IOException e) {
                    // Error
    
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // For the example, you can show an error dialog or a toast
                            // on the main UI thread
                        }
                    });
                }
    
                @Override
                public void onResponse(Call call, final Response response) throws IOException {
                    String res = response.body().string();
    
                    // Do something with the response
                }
            });
    }