Подтвердить что ты не робот

Использование API Google Cloud Print с Android

Я работаю над приложением для Android, которое нужно печатать на принтере. Я решил использовать Виртуальный принтер Google, так как он был легко настроен. Первоначально я выполнил шаги, найденные здесь для интеграции в Android. Это работает, так как в нем будет печататься на моем желаемом принтере. Однако этот процесс немного зависит от пользователя. В моем случае процесс выглядит следующим образом:

  • Пользователь выбирает кнопку печати, которую я отобразил рядом с некоторой информацией.
  • Диалог показан с предварительным просмотром распечатки. В ActionBar есть кнопка с надписью "Печать" . Это начинает процесс.
  • Отображается новое действие, показывающее список принтеров, которые подключены к этой учетной записи Google. Пользователь должен выбрать один.
  • Отображается новая страница с описанием задания на печать.
  • Пользователь должен выбрать "Печать" в правом верхнем углу.
  • Запускается задание на печать, и принтер распечатывает изображение.

К сожалению, мой клиент не хочет этого процесса. Они хотят, чтобы пользователь нажимал "Печать" на втором шаге, а затем печатал изображение (шаги 1, 2 и 6). Таким образом, я не могу использовать Intent, предоставляемые Google, я должен использовать фактический API. Это требует от меня получения токена Google Auth, получения требуемого принтера и отправки задания печати таким образом. Я делаю следующее:

  • Используйте Службы Google Play для извлечения токена OAuth для учетной записи пользователя Gmail.
  • Получить список принтеров с помощью вызова /search API.
  • Отправьте задание на печать с помощью вызова API/submit API.

У меня есть первые два. У меня просто проблемы с фактической печатью изображения. Вместо того, чтобы печатать изображение, печатаются данные байта изображения (кодировка Base64). Вот какой код, как я отправляю запрос:

ContentResolver contentResolver = context.getContentResolver();
try {
    InputStream is = contentResolver.openInputStream(uri);
    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();

    content = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
    Log.d(TAG, "File not found: " + uri.toString(), e);
} catch (IOException e) {
    e.printStackTrace();
}

Этот код извлекает изображение (переменная "uri" - это URI этого файла) и превращает ее в кодировку Base64. Это тот же метод, который используется в PrintDialogActivity, который указан на странице Виртуального принтера Google (связанный с выше). Ниже приводится способ отправки этого сообщения:

Насколько я могу судить, так оно и должно быть. При печати вы получаете ответ { "success": true}. Но, как я сказал выше, он печатает фактическую строку данных Base64. Любая помощь будет оценена по достоинству.

РЕДАКТИРОВАТЬ: Используя то, что сказано ниже, я смог это исправить. Вместо использования вышеприведенного кода я использовал следующее:

public void submitPrintJobWithFile(String printerId, String title, String token, String filePath, String contentType){
    File file = new File(filePath);
    // Method that gets the correct headers
    List<Header> headers = getHeaders(contentType, token);
    // Method that gets the correct post parameters
    String url = CLOUDPRINT_URL + PATH_SUBMIT;
    List<NameValuePair> postParams = getParams(title, contentType);
    String params = "access_token=" + token + "&cookies=false" + "&printerid=" + printerId;
    url += params;
    response = sendMultipartData(url, file, postParams, headers);
}

private String sendMultipartData(String url, File file, List<NameValuePair> fields, List<Header> headers){
    HttpPost post = new HttpPost(url);
    MultipartEntity entity = new MultipartEntity();
    for(NameValuePair pair : fields){
        String name = pair.getName();
        String value = pair.getValue();
        try{
            entity.addPart(name, new StringBody(value));
        }catch (UnsupportedEncodingException e){
            Log.d(TAG, "Error turning pair (name=" + name + ", value=" + value + ") into StringBody.");
    }
    entity.addPart("content", new FileBody(file));
    post.setEntity(entity);
    // Finish HttpClient request here...
}
4b9b3361

Ответ 1

Похоже, вам нужно использовать многостраничную кодировку, например здесь:

http://blog.tacticalnuclearstrike.com/2010/01/using-multipartentity-in-android-applications/

FTA:

Необходимыми файлами являются apache-mime4j, httpclient, httpcore и httpmime. Все это проекты с открытым исходным кодом, созданные фундаментом Apache.

Загрузите 4 файла и добавьте их в свой проект, тогда вы сможете использовать следующий код для размещения строк и файлов на страницах.

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.tumblr.com/api/write");

try {
    MultipartEntity entity = new MultipartEntity();

    entity.addPart("type", new StringBody("photo"));
    entity.addPart("data", new FileBody(image));
    httppost.setEntity(entity);
    HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
} catch (IOException e) {
} 

В этом случае переменная изображения представляет собой файл, содержащий изображение, снятое камерой на телефоне.

Ответ 2

Глядя на Пример кода Python Метод SubmitJob кажется, что в Base64 должны быть закодированы только типы PDF.

Ответ 3

Отвечая на вопрос с небольшим обновлением. По состоянию на октябрь 2013 года в 4.4 и в библиотеке поддержки были встроены методы обработки печати. Для правильной работы см. Следующую документацию: