英文:
How can I interop with Android project java in .NET MAUI Project?
问题
我尝试在.NET MAUI Blazor混合项目中打印文档。在这个过程中,我注意到了在platform/android文件夹根目录下与Android操作系统进行交互的地方。以下是我在开发该打印代码时所遵循的文档:
在Android上打印照片是成功的,但现在我想打印自定义文档,因为我想打印PDF。以下是成功打印图像和不成功打印PDF的代码。PDF和图像都可以转换为Base64字符串。
以下是.NET中的接口代码:
namespace PrintMAUI.Services
{
public interface IPrintCalller
{
Task<bool> printImage(byte[] bitmapBytes);
Task<bool> printPDF(byte[] pdfBytes);
}
}
在Android平台上创建的类代码:
namespace PrintMAUI.Platforms
{
public class PrintCaller : MauiAppCompatActivity, IPrintCalller
{
public async Task<bool> printImage(byte[] bitmapBytes)
{
try
{
//Microsoft.Maui.ApplicationModel.Platform.CurrentActivity.Context
PrintHelper photoPrinter = new PrintHelper(Platform.CurrentActivity);
photoPrinter.ScaleMode = PrintHelper.ScaleModeFill;
Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync(bitmapBytes, 0, bitmapBytes.Length);
photoPrinter.PrintBitmap("Testing Print for BL", bitmap);
return true;
}
catch (Exception ex)
{
return false;
}
}
public async Task<bool> printPDF(byte[] pdfBytes)
{
try
{
PrintManager printManager = Platform.CurrentActivity.GetSystemService(Android.Content.Context.PrintService).JavaCast<PrintManager>();
string jobName = "simple Print Job";
printManager.Print(jobName, new CustomPrintDocumentAdapter(pdfBytes), null);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
}
自定义打印适配器代码:
using Android.Graphics.Pdf;
using Android.OS;
using Android.Print;
using Android.Print.Pdf;
using Android.Runtime;
using Java.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Android.Print.PrintAttributes;
namespace PrintMAUI.Platforms
{
public class CustomPrintDocumentAdapter : PrintDocumentAdapter
{
//private byte[] data;
private int totalPages = 0;
PrintedPdfDocument pdfDocument;
public CustomPrintDocumentAdapter(byte[] data)
{
//this.data = data;
}
public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
pdfDocument = new PrintedPdfDocument(Platform.CurrentActivity, newAttributes);
if (cancellationSignal.IsCanceled)
{
callback.OnLayoutCancelled();
return;
}
int pages = computePageCount(newAttributes);
if (pages > 0)
{
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("PDF.pdf")
.SetContentType(Android.Print.PrintContentType.Document)
.SetPageCount(pages)
.Build();
callback.OnLayoutFinished(pdi, true);
}
else
{
callback.OnLayoutFailed("Calculations Failed!");
}
}
private bool containsPage(PageRange[] pages, int num)
{
//TODO: you have to do it
return true;
}
public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
{
for (int i = 0; i < totalPages; i++)
{
// Check to see if this page is in the output range.
if (containsPage(pages, i))
{
// If so, add it to writtenPagesArray. writtenPagesArray.size()
// is used to compute the next output page index.
//writtenPagesArray.append(writtenPagesArray.size(), i);
PdfDocument.Page page = pdfDocument.StartPage(i);
// check for cancellation
if (cancellationSignal.IsCanceled)
{
callback.OnWriteCancelled();
pdfDocument.Close();
pdfDocument = null;
return;
}
// Rendering is complete, so page can be finalized.
pdfDocument.FinishPage(page);
}
}
// Write PDF document to file
try
{
//FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
pdfDocument.WriteTo(stream);
}
catch (Exception e)
{
callback.OnWriteFailed(e.ToString());
return;
}
finally
{
pdfDocument.Close();
pdfDocument = null;
}
//PageRange[] writtenPages = computeWrittenPages();
/// Signal the print framework the document is complete
callback.OnWriteFinished(pages);
}
private int computePageCount(PrintAttributes printAttributes)
{
int itemsPerPage = 4;
MediaSize pageSize = printAttributes.GetMediaSize();
if (!pageSize.IsPortrait)
{
itemsPerPage = 6;
}
int printItemCount = 1;
return (int)Math.Ceiling((double)printItemCount/itemsPerPage);
}
}
}
我的做法
-
首先,我尝试创建一个单独的项目,其中包含打印机SDK,并从MAUI应用程序调用它。但由于策略限制,这并不起作用。
-
然后我尝试将打印机SDK添加到MAUI项目中。但这也不起作用。
-
然后我尝试这种方法。我尝试使用Android打印管理器来打印文档。我成功地打印了图像,但我想从字节数组中打印PDF。
我的期望
在CustomPrintDocumentAdapter类中,以下代码行存在问题,无法修复。无论如何,我都会得到转换问题:
FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
pdfDocument.WriteTo(stream);
我想知道如何修复它?
其次,我认为这段代码可能有一些需要理解的地方,即CustomPrintDocumentAdapter如何支持打印自定义文档。有人能解释一下吗?
Google文档中有这段代码:
writtenPagesArray.append(writtenPages
<details>
<summary>英文:</summary>
I tried to print documents over .NET MAUI Blazor hybrid Project. When I was doing it, I saw the place interop with android os in platform/android folder root. Here is the documentation I followed when developing that code to print,
1. [Printing Photos in android Print manager](https://developer.android.com/training/printing/photos)
2. [Printing Custom Document in android](https://developer.android.com/training/printing/custom-docs)
Printing photos in android is a success, but now I want to print custom documents because I want to print PDF. Here is a code for successful image print and unsuccessful PDF Print. Both PDF and image can convert to base64 string.
here is code of interface in .NET
namespace PrintMAUI.Services
{
public interface IPrintCalller
{
Task<bool> printImage(byte[] bitmapBytes);
Task<bool> printPDF(byte[] pdfBytes);
}
}
Class Created for android platform
namespace PrintMAUI.Platforms
{
public class PrintCaller : MauiAppCompatActivity, IPrintCalller
{
public async Task<bool> printImage(byte[] bitmapBytes)
{
try
{
//Microsoft.Maui.ApplicationModel.Platform.CurrentActivity.Context
PrintHelper photoPrinter = new PrintHelper(Platform.CurrentActivity);
photoPrinter.ScaleMode = PrintHelper.ScaleModeFill;
Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync(bitmapBytes, 0, bitmapBytes.Length);
photoPrinter.PrintBitmap("Testing Print for BL", bitmap);
return true;
}catch (Exception ex)
{
return false;
}
}
public async Task<bool> printPDF(byte[] pdfBytes)
{
try
{
PrintManager printManager = Platform.CurrentActivity.GetSystemService(Android.Content.Context.PrintService).JavaCast<PrintManager>();
string jobName = "simple Print Job";
printManager.Print(jobName, new CustomPrintDocumentAdapter(pdfBytes), null);
return true;
}catch(Exception ex)
{
return false;
}
}
}
}
Custom Print Adapter
using Android.Graphics.Pdf;
using Android.OS;
using Android.Print;
using Android.Print.Pdf;
using Android.Runtime;
using Java.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Android.Print.PrintAttributes;
namespace PrintMAUI.Platforms
{
public class CustomPrintDocumentAdapter : PrintDocumentAdapter
{
//private byte[] data;
private int totalPages = 0;
PrintedPdfDocument pdfDocument;
public CustomPrintDocumentAdapter(byte[] data)
{
//this.data = data;
}
public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
pdfDocument = new PrintedPdfDocument(Platform.CurrentActivity,newAttributes);
if (cancellationSignal.IsCanceled)
{
callback.OnLayoutCancelled();
return;
}
int pages = computePageCount(newAttributes);
if(pages > 0)
{
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("PDF.pdf")
.SetContentType(Android.Print.PrintContentType.Document)
.SetPageCount(pages)
.Build();
callback.OnLayoutFinished(pdi, true);
}
else
{
callback.OnLayoutFailed("Calculations Failed!");
}
}
private bool containsPage(PageRange[] pages,int num)
{
//TODO: you have to do it
return true;
}
public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
{
for (int i = 0; i < totalPages; i++)
{
// Check to see if this page is in the output range.
if (containsPage(pages, i))
{
// If so, add it to writtenPagesArray. writtenPagesArray.size()
// is used to compute the next output page index.
//writtenPagesArray.append(writtenPagesArray.size(), i);
PdfDocument.Page page = pdfDocument.StartPage(i);
// check for cancellation
if (cancellationSignal.IsCanceled)
{
callback.OnWriteCancelled();
pdfDocument.Close();
pdfDocument = null;
return;
}
// Rendering is complete, so page can be finalized.
pdfDocument.FinishPage(page);
}
}
// Write PDF document to file
try
{
//FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
pdfDocument.WriteTo(stream);
}
catch (Exception e)
{
callback.OnWriteFailed(e.ToString());
return;
}
finally
{
pdfDocument.Close();
pdfDocument = null;
}
//PageRange[] writtenPages = computeWrittenPages();
/// Signal the print framework the document is complete
callback.OnWriteFinished(pages);
}
private int computePageCount(PrintAttributes printAttributes)
{
int itemsPerPage = 4;
MediaSize pageSize = printAttributes.GetMediaSize();
if (!pageSize.IsPortrait)
{
itemsPerPage = 6;
}
int printItemCount = 1;
return (int)Math.Ceiling((double)printItemCount/itemsPerPage);
}
}
}
### What I does
1. First I try to create seperate project with printer SDK and call to it from MAUI app. but it didn's work because policy restrictions.
2. Then I try to add printer SDK to MAUI Project. It doesn't work
3. Then I try to this way.I try to use android print manager to print documents. I successful when printing image. but I want to print PDF from it's byte array.
### What I Expecting
these lines in customprintdocumentadapter class got issue that cannot be fixed. everyway I got casting issue
FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
pdfDocument.WriteTo(stream);
I want way to fix it?
Second thing is I thaught this code may have some ponts that have to be understand how customprintdocumentadapter support to print custom document. can someone explain?
google documentation have this code
writtenPagesArray.append(writtenPagesArray.size(), i);
but I cant find where is coming from.
</details>
# 答案1
**得分**: 0
实际上不想创建PrintedPdfDocument对象。我可以像这样将我的字节数组传递给文件流:
```csharp
public class CustomPrintDocumentAdapter : PrintDocumentAdapter
{
private byte[] data;
public CustomPrintDocumentAdapter(byte[] data)
{
this.data = data;
}
public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
if (cancellationSignal.IsCanceled)
{
callback.OnLayoutCancelled();
return;
}
int pages = 1;
if (pages > 0)
{
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("PDF.pdf")
.SetContentType(Android.Print.PrintContentType.Document)
.SetPageCount(pages)
.Build();
callback.OnLayoutFinished(pdi, true);
}
else
{
callback.OnLayoutFailed("Calculations Failed!");
}
}
public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
{
try
{
FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
stream.Write(data);
}
catch (Exception e)
{
callback.OnWriteFailed(e.ToString());
return;
}
callback.OnWriteFinished(pages);
}
}
然后问题得以解决。
英文:
Actually Not wanted to create PrintedPdfDocument Object. I could able to pass my byte array to filestream like this
public class CustomPrintDocumentAdapter : PrintDocumentAdapter
{
private byte[] data;
public CustomPrintDocumentAdapter(byte[] data)
{
this.data = data;
}
public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
if (cancellationSignal.IsCanceled)
{
callback.OnLayoutCancelled();
return;
}
int pages = 1;
if (pages > 0)
{
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("PDF.pdf")
.SetContentType(Android.Print.PrintContentType.Document)
.SetPageCount(pages)
.Build();
callback.OnLayoutFinished(pdi, true);
}
else
{
callback.OnLayoutFailed("Calculations Failed!");
}
}
public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
{
try
{
FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
stream.Write(data);
}
catch (Exception e)
{
callback.OnWriteFailed(e.ToString());
return;
}
callback.OnWriteFinished(pages);
}
}
Then Problem get solved
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论