[java]
<span style="font-size:18px;"></span>
最近在做關於Android的項目,Android果然不是出於國內,很多東西都是國外已經成熟瞭或者已經開發好瞭,國內去效仿。為瞭找關於Android無線連接打印機並打印的第三方開發方案都非常的困難。由於最近項目需要用到這一塊,經過我的組員的努力,找到瞭一種解決方案,為瞭能夠和大傢分享一下,也為瞭自己以後的參考,在這裡稍作總結一下。經驗有限,希望有更好方案的可以不吝賜教,我也會在以後的學習中不斷修繕自己的方案。
為瞭便於大傢的參考,本文涉及到的所有的相關工程文件都在本人的csdn下載部分有相關資料下載。
1.背景:
很多開發者在工作上或者學習中可能需要通過基於Android系統的手機或者平板終端連接打印機,並驅動打
印機打印自己發送的圖片或者文本。本篇博客主要致力於解決這個問題。
2.方案:
本方案需要在android系統中安裝一個軟件send2print,在我的csdn下載頻道中有相應的中文破解版下載鏈
接,然後再寫自己的程序,來調用其接口進行打印。事先需要在send2print中配置好默認打印機,我們寫的程序
就是調用其默認打印機進行無線打印。
這個軟件可以安裝直接使用,可以搜索開著無線的打印機,並連接進行打印,目前隻有國外有賣該產品,
國內網上可以下載漢化版,我的csdn下載中也有。漢化版有一定的缺陷,經過測試,佳能產品的大部分型號
都無法實現打印,但是HP LaserJet 1536dnf MFP可以實現打印。
4.代碼實現 我也不想貼代碼,但是,安裝好之後,配置上默認打印機,你隻需要兩個類就可以輕松實現無線打印瞭,
由於代碼量不大,也很容易看懂,我就直接貼在下面瞭,如果需要測試打印的資源文件可以到我csdn下載頻道
下載,這該死的博客怎麼沒有直接上傳資源功能,還是我沒有發現啊,誰發現瞭告訴我一聲啊,嘿嘿。
PrintUtils.java
[html]
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 logging
private static final String TAG = PrintUtils.class.getSimpleName();
// Send 2 Printer package name
private static final String PACKAGE_NAME = "com.rcreations.send2printer";
// intent action to trigger printing
public 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 /wp-content/images1/20181015/20120821021535608117.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() {
@Override
public void onClick( DialogInterface dialog, int which )
{
// launch browser
Uri 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 );
// exit
context.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=/wp-content/images1/20181015/20120821021535608117.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
[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 String TAG = 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() {
@Override
public void onClick(View v)
{
printCanvasExample();
}
});
Button btnTestCanvasAsBitmap = (Button)findViewById( R.id.btnTestCanvasAsBitmap );
btnTestCanvasAsBitmap.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v)
{
printCanvasAsBitmapExample();
}
});
Button btnTestText = (Button)findViewById( R.id.btnTestText );
btnTestText.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v)
{
printTextExample();
}
});
Button btnTestHtml = (Button)findViewById( R.id.btnTestHtml );
btnTestHtml.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v)
{
printHtmlExample();
}
});
Button btnTestHtmlUrl = (Button)findViewById( R.id.btnTestHtmlUrl );
btnTestHtmlUrl.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v)
{
printHtmlUrlExample();
}
});
Button btnTestTextFile = (Button)findViewById( R.id.btnTestTextFile );
btnTestTextFile.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v)
{
printTextFileExample();
}
});
Button btnTestHtmlFile = (Button)findViewById( R.id.btnTestHtmlFile );
btnTestHtmlFile.setOnClickListener( new View.OnClickListener() {
@Override
public 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=/wp-content/images1/20181015/20120821021535595118.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=\/wp-content/images1/20181015/20120821021535608117.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=/wp-content/images1/20181015/20120821021535595118.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=\/wp-content/images1/20181015/20120821021535608117.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!