Android无线连接打印第三方开发的实现
最近在做关于Android的项目,Android果然不是出于国内,很多东西都是国外已经成熟了或者已经开发好了,国内去效仿。为了找关于Android无线连接打印机并打印的第三方开发方案都非常的困难。由于最近项目需要用到这一块,经过我的组员的努力,找到了一种解决方案,为了能够和大家分享一下,也为了自己以后的参考,在这里稍作总结一下。经验有限,希望有更好方案的可以不吝赐教,我也会在以后的学习中不断修缮自己的方案。
为了便于大家的参考,本文涉及到的所有的相关工程文件都在本人的csdn下载部分有相关资料下载。
1.背景:
很多开发者在工作上或者学习中可能需要通过基于Android系统的手机或者平板终端连接打印机,并驱动打
印机打印自己发送的图片或者文本。本篇博客主要致力于解决这个问题。
2.方案:
本方案需要在android系统中安装一个软件send2print,在我的csdn下载频道中有相应的中文破解版下载链
接,然后再写自己的程序,来调用其接口进行打印。事先需要在send2print中配置好默认打印机,我们写的程序
就是调用其默认打印机进行无线打印。
3.send2print:(我的csdn下载:http://download.csdn.net/detail/kunlong0909/4514502)
这个软件可以安装直接使用,可以搜索开着无线的打印机,并连接进行打印,目前只有国外有卖该产品,
国内网上可以下载汉化版,我的csdn下载中也有。汉化版有一定的缺陷,经过测试,佳能产品的大部分型号
都无法实现打印,但是HP LaserJet 1536dnf MFP可以实现打印。
4.代码实现:(我的csdn工程源码下载:http://download.csdn.net/detail/kunlong0909/4514570)
我也不想贴代码,但是,安装好之后,配置上默认打印机,你只需要两个类就可以轻松实现无线打印了,
由于代码量不大,也很容易看懂,我就直接贴在下面了,如果需要测试打印的资源文件可以到我csdn下载频道
下载,这该死的博客怎么没有直接上传资源功能,还是我没有发现啊,谁发现了告诉我一声啊,嘿嘿。
PrintUtils.java
package com.rcreations.testprint;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import android.app.Activity;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.Picture;import android.net.Uri;import android.os.Environment;import android.util.Log;public class PrintUtils{// for loggingprivate static final StringTAG= PrintUtils.class.getSimpleName();// Send 2 Printer package nameprivate static final String PACKAGE_NAME = "com.rcreations.send2printer";// intent action to trigger printingpublic static final String PRINT_ACTION = "com.rcreations.send2printer.print";// content provider for accessing images on local sdcard from within html content// sample img src shoul be something like "content://s2p_localfile/sdcard/logo.gif"public static final String LOCAL_SDCARD_CONTENT_PROVIDER_PREFIX = "content://s2p_localfile";/** * Returns true if "Send 2 Printer" is installed. */public static boolean isSend2PrinterInstalled( Context context ){boolean output = false;PackageManager pm = context.getPackageManager(); try { PackageInfo pi = pm.getPackageInfo( PACKAGE_NAME, 0 ); if( pi != null ) { output = true; } } catch (PackageManager.NameNotFoundException e) {} return output;}/** * Launches the Android Market page for installing "Send 2 Printer" * and calls "finish()" on the given activity. */public static void launchMarketPageForSend2Printer( final Activity context ){ AlertDialog dlg = new AlertDialog.Builder( context ) .setTitle("Install Send 2 Printer") .setMessage("Before you can print to a network printer, you need to install Send 2 Printer from the Android Market.") .setPositiveButton( android.R.string.ok, new DialogInterface.OnClickListener() {@Overridepublic void onClick( DialogInterface dialog, int which ){// launch browserUri data = Uri.parse( "http://market.android.com/search?q=pname:" + PACKAGE_NAME );Intent intent = new Intent( android.content.Intent.ACTION_VIEW, data );intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );context.startActivity( intent );// exitcontext.finish();} } ) .show();} /** * Save the given picture (contains canvas draw commands) to a file for printing. */ public static File saveCanvasPictureToTempFile( Picture picture ) { File tempFile = null; // save to temporary file File dir = getTempDir(); if( dir != null ) {FileOutputStream fos = null;try{File f = File.createTempFile( "picture", ".stream", dir );fos = new FileOutputStream( f );picture.writeToStream( fos );tempFile = f;}catch( IOException e ){Log.e( TAG, "failed to save picture", e );}finally{close( fos );} } return tempFile; } /** * Sends the given picture file (returned from {@link #saveCanvasPictureToTempFile}) for printing. */ public static boolean queuePictureStreamForPrinting( Context context, File f ) { // send to print activity Uri uri = Uri.fromFile( f ); Intent i = new Intent( PRINT_ACTION ); i.setDataAndType( uri, "application/x-android-picture-stream" ); i.putExtra( "scaleFitToPage", true ); context.startActivity( i ); return true; } /** * Save the given Bitmap to a file for printing. * Note: Bitmap can be result of canvas draw commands. */ public static File saveBitmapToTempFile( Bitmap b, Bitmap.CompressFormat format ) throws IOException, UnknownFormatException { File tempFile = null; // save to temporary file File dir = getTempDir(); if( dir != null ) {FileOutputStream fos = null;try{String strExt = null;switch( format ){case PNG:strExt = ".pngx";break;case JPEG:strExt = ".jpgx";break;default:throw new UnknownFormatException( "unknown format: " + format );}File f = File.createTempFile( "bitmap", strExt, dir );fos = new FileOutputStream( f );b.compress( format, 100, fos );tempFile = f;}finally{close( fos );} } return tempFile; } /** * Sends the given image file for printing. */ public static boolean queueBitmapForPrinting( Context context, File f, Bitmap.CompressFormat format ) throws UnknownFormatException { String strMimeType = null;switch( format ){case PNG:strMimeType = "image/png";break;case JPEG:strMimeType = "image/jpeg";break;default:throw new UnknownFormatException( "unknown format: " + format );} // send to print activity Uri uri = Uri.fromFile( f ); Intent i = new Intent( PRINT_ACTION ); i.setDataAndType( uri, strMimeType ); i.putExtra( "scaleFitToPage", true ); i.putExtra( "deleteAfterPrint", true ); context.startActivity( i ); return true; } /** * Sends the given text for printing. */ public static boolean queueTextForPrinting( Context context, String strContent ) { // send to print activity Intent i = new Intent( PRINT_ACTION ); i.setType( "text/plain" ); i.putExtra( Intent.EXTRA_TEXT, strContent ); context.startActivity( i ); return true; } /** * Save the given text to a file for printing. */ public static File saveTextToTempFile( String text ) throws IOException { File tempFile = null; // save to temporary file File dir = getTempDir(); if( dir != null ) {FileOutputStream fos = null;try{File f = File.createTempFile( "text", ".txt", dir );fos = new FileOutputStream( f );fos.write( text.getBytes() );tempFile = f;}finally{close( fos );} } return tempFile; } /** * Sends the given text file for printing. */ public static boolean queueTextFileForPrinting( Context context, File f ) { // send to print activity Uri uri = Uri.fromFile( f ); Intent i = new Intent( PRINT_ACTION ); i.setDataAndType( uri, "text/plain" ); i.putExtra( "deleteAfterPrint", true ); context.startActivity( i ); return true; } /** * Sends the given html for printing. * * You can also reference a local image on your sdcard using the "content://s2p_localfile" provider. * For example: <img src="content://s2p_localfile/sdcard/logo.gif"> */ public static boolean queueHtmlForPrinting( Context context, String strContent ) { // send to print activity Intent i = new Intent( PRINT_ACTION ); i.setType( "text/html" ); i.putExtra( Intent.EXTRA_TEXT, strContent ); context.startActivity( i ); return true; } /** * Sends the given html URL for printing. * * You can also reference a local file on your sdcard using the "content://s2p_localfile" provider. * For example: "content://s2p_localfile/sdcard/test.html" */ public static boolean queueHtmlUrlForPrinting( Context context, String strUrl ) { // send to print activity Intent i = new Intent( PRINT_ACTION ); //i.setDataAndType( Uri.parse(strUrl), "text/html" );// this crashes! i.setType( "text/html" ); i.putExtra( Intent.EXTRA_TEXT, strUrl ); context.startActivity( i ); return true; } /** * Save the given html content to a file for printing. */ public static File saveHtmlToTempFile( String html ) throws IOException { File tempFile = null; // save to temporary file File dir = getTempDir(); if( dir != null ) {FileOutputStream fos = null;try{File f = File.createTempFile( "html", ".html", dir );fos = new FileOutputStream( f );fos.write( html.getBytes() );tempFile = f;}finally{close( fos );} } return tempFile; } /** * Sends the given html file for printing. */ public static boolean queueHtmlFileForPrinting( Context context, File f ) { // send to print activity Uri uri = Uri.fromFile( f ); Intent i = new Intent( PRINT_ACTION ); i.setDataAndType( uri, "text/html" ); i.putExtra( "deleteAfterPrint", true ); context.startActivity( i ); return true; } /** * Return a temporary directory on the sdcard where files can be saved for printing. * @return null if temporary directory could not be created. */public static File getTempDir(){File dir = new File( Environment.getExternalStorageDirectory(), "temp" );if( dir.exists() == false && dir.mkdirs() == false ){Log.e( TAG, "failed to get/create temp directory" );return null;}return dir;} /** * Helper method to close given output stream ignoring any exceptions. */ public static void close( OutputStream os ) { if( os != null ) { try { os.close(); } catch( IOException e ) {} } } /** * Thrown by bitmap methods where the given Bitmap.CompressFormat value is unknown. */ public static class UnknownFormatException extends Exception { public UnknownFormatException( String msg ) { super( msg ); } }}
以上是工具类,下面的是测试类:
MainActivity.java
package com.rcreations.testprint;import java.io.File;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Picture;import android.graphics.Rect;import android.graphics.Typeface;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;/** * Various print samples. */public class MainActivity extends Activity{private static final StringTAG= MainActivity.class.getSimpleName();static final String HELLO_WORLD = "Hello World";/** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // // check for and install Send 2 Printer if needed // if( PrintUtils.isSend2PrinterInstalled(this) == false ) { PrintUtils.launchMarketPageForSend2Printer( this ); return; } // // setup GUI buttons // Button btnTestCanvas = (Button)findViewById( R.id.btnTestCanvas ); btnTestCanvas.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printCanvasExample();} }); Button btnTestCanvasAsBitmap = (Button)findViewById( R.id.btnTestCanvasAsBitmap ); btnTestCanvasAsBitmap.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printCanvasAsBitmapExample();} }); Button btnTestText = (Button)findViewById( R.id.btnTestText ); btnTestText.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printTextExample();} }); Button btnTestHtml = (Button)findViewById( R.id.btnTestHtml ); btnTestHtml.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printHtmlExample();} }); Button btnTestHtmlUrl = (Button)findViewById( R.id.btnTestHtmlUrl ); btnTestHtmlUrl.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printHtmlUrlExample();} }); Button btnTestTextFile = (Button)findViewById( R.id.btnTestTextFile ); btnTestTextFile.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printTextFileExample();} }); Button btnTestHtmlFile = (Button)findViewById( R.id.btnTestHtmlFile ); btnTestHtmlFile.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v){printHtmlFileExample();} }); } /** * Send canvas draw commands for printing. * NOTE: Android 1.5 does not properly support drawBitmap() serialize/deserialize across process boundaries. * If you need to draw bitmaps, then see the {@link #printCanvasAsBitmapExample()} example. */ void printCanvasExample() { // create canvas to render on Picture picture = new Picture(); Canvas c = picture.beginRecording( 240, 240 ); // fill background with WHITE c.drawRGB( 0xFF, 0xFF, 0xFF ); // draw text Paint p = new Paint(); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD); p.setTextSize( 18 ); p.setTypeface( font ); p.setAntiAlias(true); Rect textBounds = new Rect(); p.getTextBounds( HELLO_WORLD, 0, HELLO_WORLD.length(), textBounds ); int x = (c.getWidth() - (textBounds.right-textBounds.left)) / 2; int y = (c.getHeight() - (textBounds.bottom-textBounds.top)) / 2; c.drawText( HELLO_WORLD, x, y, p ); // draw icon Bitmap icon = BitmapFactory.decodeResource( getResources(), R.drawable.icon ); c.drawBitmap( icon, 0, 0, null ); // stop drawing picture.endRecording(); // queue canvas for printing File f = PrintUtils.saveCanvasPictureToTempFile( picture ); if( f != null ) { PrintUtils.queuePictureStreamForPrinting( this, f ); } } /** * Draw to a bitmap and then send the bitmap for printing. */ void printCanvasAsBitmapExample() { // create canvas to render on Bitmap b = Bitmap.createBitmap( 240, 240, Bitmap.Config.RGB_565 ); Canvas c = new Canvas( b ); // fill background with WHITE c.drawRGB( 0xFF, 0xFF, 0xFF ); // draw text Paint p = new Paint(); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD); p.setTextSize( 18 ); p.setTypeface( font ); p.setAntiAlias(true); Rect textBounds = new Rect(); p.getTextBounds( HELLO_WORLD, 0, HELLO_WORLD.length(), textBounds ); int x = (c.getWidth() - (textBounds.right-textBounds.left)) / 2; int y = (c.getHeight() - (textBounds.bottom-textBounds.top)) / 2; c.drawText( HELLO_WORLD, x, y, p ); // draw icon Bitmap icon = BitmapFactory.decodeResource( getResources(), R.drawable.icon ); c.drawBitmap( icon, 0, 0, null ); // queue bitmap for printing try { File f = PrintUtils.saveBitmapToTempFile( b, Bitmap.CompressFormat.PNG ); if( f != null ) { PrintUtils.queueBitmapForPrinting( this, f, Bitmap.CompressFormat.PNG ); } } catch( Exception e ) { Log.e( TAG, "failed to save/queue bitmap", e ); } } /** * Send text for printing. */ void printTextExample() {PrintUtils.queueTextForPrinting( this, HELLO_WORLD ); } /** * Send html for printing. */ void printHtmlExample() {StringBuilder buf = new StringBuilder();buf.append( "<html>" );buf.append( "<body>" );buf.append( "<h1>" ).append( HELLO_WORLD ).append( "</h1>" ); buf.append( "<p>" ).append( "blah blah blah..." ).append( "</p>" ); buf.append( "<p><img src=\"http://www.google.com/intl/en_ALL/images/logo.gif\" /></p>" );// you can also reference a local image on your sdcard using the "content://s2p_localfile" provider (see below) //buf.append( "<p><img src=\"content://s2p_localfile/sdcard/logo.gif\" /></p>" );buf.append( "</body>" ); buf.append( "</html>" );PrintUtils.queueHtmlForPrinting( this, buf.toString() ); } /** * Send html URL for printing. */ void printHtmlUrlExample() {PrintUtils.queueHtmlUrlForPrinting( this, "http://www.google.com" ); } /** * Send text file for printing. */ void printTextFileExample() { try { File f = PrintUtils.saveTextToTempFile( HELLO_WORLD ); if( f != null ) { PrintUtils.queueTextFileForPrinting( this, f ); } } catch( Exception e ) { Log.e( TAG, "failed to save/queue text", e ); } } /** * Send html file for printing. */ void printHtmlFileExample() { try { StringBuilder buf = new StringBuilder(); buf.append( "<html>" ); buf.append( "<body>" ); buf.append( "<h1>" ).append( HELLO_WORLD ).append( "</h1>" ); buf.append( "<p>" ).append( "blah blah blah..." ).append( "</p>" ); buf.append( "<p><img src=\"http://www.google.com/intl/en_ALL/images/logo.gif\" /></p>" ); // you can also reference a local image on your sdcard using the "content://s2p_localfile" provider (see below) //buf.append( "<p><img src=\"content://s2p_localfile/sdcard/logo.gif\" /></p>" ); buf.append( "</body>" ); buf.append( "</html>" ); File f = PrintUtils.saveHtmlToTempFile( buf.toString() ); if( f != null ) { PrintUtils.queueHtmlFileForPrinting( this, f ); } } catch( Exception e ) { Log.e( TAG, "failed to save/queue html", e ); } } }
其实整体上的逻辑很简单,连接无线打印机和驱动打印都是通过send2printer来实现的,我们只是需要调用它,将我们需要打印的信息发送给它就行,so easy!