Thursday, October 24, 2013

Android Printer Integration | Google Cloud Printing in Android Application | Printer demo in Android

Hello Dear Friends,

My this post is based on "How to Integrate printer in android app". the best way of doing that Google cloud printing. Google provide us Print Dialog code, we can use it in our application. Important steps are given below-

1)Login with your gamil-id in your desktop and add your printers in your browser.
2)Create a demo app and put below code.
3)Add Internet permissions and read storage.
<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />





1)MainActivity.java
package com.manish.googleprintdemo;

import java.io.File;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
/**
 *
 * @author manish
 *
 */

public class MainActivity extends Activity {
       Button btnPrint;
       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              btnPrint=(Button)findViewById(R.id.button1);
             
              btnPrint.setOnClickListener(new OnClickListener() {
                    
                     @Override
                     public void onClick(View v) {
                           // TODO Auto-generated method stub

                            if (isNetworkAvailable() == false) {
                                         Toast.makeText(MainActivity.this,
                                                       "Network connection not available, Please try later",
                                                       Toast.LENGTH_SHORT).show();
                                  } else {
                                         File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/personal/xyz.pdf");
                                         Intent printIntent = new Intent(MainActivity.this, PrintDialogActivity.class);
                                         printIntent.setDataAndType(Uri.fromFile(file), "application/pdf");
                                         printIntent.putExtra("title", "Android print demo");
                                         startActivity(printIntent);
                                  }
                     }
              });
       }

       public boolean isNetworkAvailable() {

              ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
              NetworkInfo networkInfo = cm.getActiveNetworkInfo();
              // if no network is available networkInfo will be null
              // otherwise check if we are connected
              if (networkInfo != null && networkInfo.isConnected()) {
                     Log.e("Network Testing", "***Available***");
                     return true;
              }
              Log.e("Network Testing", "***Not Available***");
              return false;
       }

}

2)PrintDialogActivity.java

package com.manish.googleprintdemo;

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;

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);

    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)");
      }
    }
  }
}



3)activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Print" />

</RelativeLayout>


4)print_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>


5)AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.manish.googleprintdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.manish.googleprintdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".PrintDialogActivity" />
    </application>

</manifest>




Thanks!

18 comments :

  1. This is awesome. I learnt a lot from your blogs. hope all will learn. Thanks for posting this.

    ReplyDelete
  2. Hey manish, I tried using your code, but everytime I try to print a document, it says "Document missing". There is no error in my address, I have checked repeatedly. Instead of using Environment.getExternalStorageDirectory().getAbsolutePath() + "/personal/xyz.pdf", i have hard - coded the path. Can you please help me?

    ReplyDelete
    Replies
    1. Hi Nancy, I think some thing wrong in your path because it is working code as you can see log screen shot. well let me suggest some thing-
      1)are you try to print pdf file?
      2)file is inside your sdcard or in phone memory? if in sdcard please move to phone memory.

      And can you print your file path log and error please? So I can suggest right way..

      Thanks

      Delete
    2. Hey Manish, I wanted to print a pdf stored in some URL, since this option seemed to be the best for the app I'm making, any suggestions on how to print a pdf stored online ?
      Thanks a lot!

      Delete
  3. Hi Manish Srivastava, Thank you for sharing. I have a question: Are there other way to print by wifi in android?

    ReplyDelete
    Replies
    1. Hi Luan,
      As this needs an internet connection, it depends at end user whether it is SIM Card internet or a wi-fi.internet. So I don't think wi-fi matters. Yes it matters if we want an internet connection. At code perspective, I don't think so. I hope you understand now.

      Delete
    2. And If you're talking about printing through wi-fi printer, you'll have to follow some steps, like scan the wi-fi device , then make a connection, and then make a request for printing. Below are some link that may help you:
      http://stackoverflow.com/questions/11344572/how-to-send-a-file-from-android-to-wifi-printer-programatically-and-print-the-fi
      http://stackoverflow.com/questions/7145787/bluetooth-printer-issue-in-android

      Delete
  4. hi Manish,
    i have added a classic Epson printer to Google drive and ur code is running as well and give the message print job added.
    But problem is I have'nt get print from printer.
    could u suggest me?
    My email-nishantgupta1205@gmail.com
    ph no:+919810680536

    ReplyDelete
    Replies
    1. follow below steps hope it will help you-
      1) login with gmail account in your desktop google chrome ans use same gmail account in your mobile device for printing.
      2)go to setting option in your chrome and from there add cloud printer which one attached to your desktop.
      3)now print from mobile device it will show you all attached printer list and choose one from them.

      Thanks,

      Delete
  5. Hello Manish,
    i have done these steps already. Problem is my file sometimes added in print jobs with error sign.
    have u any idea?

    ReplyDelete
    Replies
    1. I think you are getting data==null because of big size of attachment or any other reason. Please test on any other device is it working fine or same issue you are facing?

      Delete
  6. Hi Manish,
    Do you know how to print data by using USB hosting?. If you know please post that too.

    ReplyDelete