如何在.NET MAUI项目中与Android项目的Java代码进行互操作?

huangapple go评论158阅读模式
英文:

How can I interop with Android project java in .NET MAUI Project?

问题

我尝试在.NET MAUI Blazor混合项目中打印文档。在这个过程中,我注意到了在platform/android文件夹根目录下与Android操作系统进行交互的地方。以下是我在开发该打印代码时所遵循的文档:

  1. 在Android打印管理器中打印照片
  2. 在Android中打印自定义文档

在Android上打印照片是成功的,但现在我想打印自定义文档,因为我想打印PDF。以下是成功打印图像和不成功打印PDF的代码。PDF和图像都可以转换为Base64字符串。

以下是.NET中的接口代码:

  1. namespace PrintMAUI.Services
  2. {
  3. public interface IPrintCalller
  4. {
  5. Task<bool> printImage(byte[] bitmapBytes);
  6. Task<bool> printPDF(byte[] pdfBytes);
  7. }
  8. }

在Android平台上创建的类代码:

  1. namespace PrintMAUI.Platforms
  2. {
  3. public class PrintCaller : MauiAppCompatActivity, IPrintCalller
  4. {
  5. public async Task<bool> printImage(byte[] bitmapBytes)
  6. {
  7. try
  8. {
  9. //Microsoft.Maui.ApplicationModel.Platform.CurrentActivity.Context
  10. PrintHelper photoPrinter = new PrintHelper(Platform.CurrentActivity);
  11. photoPrinter.ScaleMode = PrintHelper.ScaleModeFill;
  12. Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync(bitmapBytes, 0, bitmapBytes.Length);
  13. photoPrinter.PrintBitmap("Testing Print for BL", bitmap);
  14. return true;
  15. }
  16. catch (Exception ex)
  17. {
  18. return false;
  19. }
  20. }
  21. public async Task<bool> printPDF(byte[] pdfBytes)
  22. {
  23. try
  24. {
  25. PrintManager printManager = Platform.CurrentActivity.GetSystemService(Android.Content.Context.PrintService).JavaCast<PrintManager>();
  26. string jobName = "simple Print Job";
  27. printManager.Print(jobName, new CustomPrintDocumentAdapter(pdfBytes), null);
  28. return true;
  29. }
  30. catch (Exception ex)
  31. {
  32. return false;
  33. }
  34. }
  35. }
  36. }

自定义打印适配器代码:

  1. using Android.Graphics.Pdf;
  2. using Android.OS;
  3. using Android.Print;
  4. using Android.Print.Pdf;
  5. using Android.Runtime;
  6. using Java.IO;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using static Android.Print.PrintAttributes;
  13. namespace PrintMAUI.Platforms
  14. {
  15. public class CustomPrintDocumentAdapter : PrintDocumentAdapter
  16. {
  17. //private byte[] data;
  18. private int totalPages = 0;
  19. PrintedPdfDocument pdfDocument;
  20. public CustomPrintDocumentAdapter(byte[] data)
  21. {
  22. //this.data = data;
  23. }
  24. public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
  25. {
  26. pdfDocument = new PrintedPdfDocument(Platform.CurrentActivity, newAttributes);
  27. if (cancellationSignal.IsCanceled)
  28. {
  29. callback.OnLayoutCancelled();
  30. return;
  31. }
  32. int pages = computePageCount(newAttributes);
  33. if (pages > 0)
  34. {
  35. PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("PDF.pdf")
  36. .SetContentType(Android.Print.PrintContentType.Document)
  37. .SetPageCount(pages)
  38. .Build();
  39. callback.OnLayoutFinished(pdi, true);
  40. }
  41. else
  42. {
  43. callback.OnLayoutFailed("Calculations Failed!");
  44. }
  45. }
  46. private bool containsPage(PageRange[] pages, int num)
  47. {
  48. //TODO: you have to do it
  49. return true;
  50. }
  51. public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
  52. {
  53. for (int i = 0; i < totalPages; i++)
  54. {
  55. // Check to see if this page is in the output range.
  56. if (containsPage(pages, i))
  57. {
  58. // If so, add it to writtenPagesArray. writtenPagesArray.size()
  59. // is used to compute the next output page index.
  60. //writtenPagesArray.append(writtenPagesArray.size(), i);
  61. PdfDocument.Page page = pdfDocument.StartPage(i);
  62. // check for cancellation
  63. if (cancellationSignal.IsCanceled)
  64. {
  65. callback.OnWriteCancelled();
  66. pdfDocument.Close();
  67. pdfDocument = null;
  68. return;
  69. }
  70. // Rendering is complete, so page can be finalized.
  71. pdfDocument.FinishPage(page);
  72. }
  73. }
  74. // Write PDF document to file
  75. try
  76. {
  77. //FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
  78. FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
  79. pdfDocument.WriteTo(stream);
  80. }
  81. catch (Exception e)
  82. {
  83. callback.OnWriteFailed(e.ToString());
  84. return;
  85. }
  86. finally
  87. {
  88. pdfDocument.Close();
  89. pdfDocument = null;
  90. }
  91. //PageRange[] writtenPages = computeWrittenPages();
  92. /// Signal the print framework the document is complete
  93. callback.OnWriteFinished(pages);
  94. }
  95. private int computePageCount(PrintAttributes printAttributes)
  96. {
  97. int itemsPerPage = 4;
  98. MediaSize pageSize = printAttributes.GetMediaSize();
  99. if (!pageSize.IsPortrait)
  100. {
  101. itemsPerPage = 6;
  102. }
  103. int printItemCount = 1;
  104. return (int)Math.Ceiling((double)printItemCount/itemsPerPage);
  105. }
  106. }
  107. }

我的做法

  1. 首先,我尝试创建一个单独的项目,其中包含打印机SDK,并从MAUI应用程序调用它。但由于策略限制,这并不起作用。

  2. 然后我尝试将打印机SDK添加到MAUI项目中。但这也不起作用。

  3. 然后我尝试这种方法。我尝试使用Android打印管理器来打印文档。我成功地打印了图像,但我想从字节数组中打印PDF。

我的期望

在CustomPrintDocumentAdapter类中,以下代码行存在问题,无法修复。无论如何,我都会得到转换问题:

  1. FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
  2. pdfDocument.WriteTo(stream);

我想知道如何修复它?

其次,我认为这段代码可能有一些需要理解的地方,即CustomPrintDocumentAdapter如何支持打印自定义文档。有人能解释一下吗?

Google文档中有这段代码:

  1. writtenPagesArray.append(writtenPages
  2. <details>
  3. <summary>英文:</summary>
  4. 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,
  5. 1. [Printing Photos in android Print manager](https://developer.android.com/training/printing/photos)
  6. 2. [Printing Custom Document in android](https://developer.android.com/training/printing/custom-docs)
  7. 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.
  8. here is code of interface in .NET

namespace PrintMAUI.Services
{
public interface IPrintCalller
{
Task<bool> printImage(byte[] bitmapBytes);
Task<bool> printPDF(byte[] pdfBytes);
}
}

  1. 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

  1. PrintHelper photoPrinter = new PrintHelper(Platform.CurrentActivity);
  2. photoPrinter.ScaleMode = PrintHelper.ScaleModeFill;
  3. Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync(bitmapBytes, 0, bitmapBytes.Length);
  4. photoPrinter.PrintBitmap(&quot;Testing Print for BL&quot;, bitmap);
  5. return true;
  6. }catch (Exception ex)
  7. {
  8. return false;
  9. }
  10. }
  11. public async Task&lt;bool&gt; printPDF(byte[] pdfBytes)
  12. {
  13. try
  14. {
  15. PrintManager printManager = Platform.CurrentActivity.GetSystemService(Android.Content.Context.PrintService).JavaCast&lt;PrintManager&gt;();
  16. string jobName = &quot;simple Print Job&quot;;
  17. printManager.Print(jobName, new CustomPrintDocumentAdapter(pdfBytes), null);
  18. return true;
  19. }catch(Exception ex)
  20. {
  21. return false;
  22. }
  23. }
  24. }

}

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

  1. if (cancellationSignal.IsCanceled)
  2. {
  3. callback.OnLayoutCancelled();
  4. return;
  5. }
  6. int pages = computePageCount(newAttributes);
  7. if(pages &gt; 0)
  8. {
  9. PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(&quot;PDF.pdf&quot;)
  10. .SetContentType(Android.Print.PrintContentType.Document)
  11. .SetPageCount(pages)
  12. .Build();
  13. callback.OnLayoutFinished(pdi, true);
  14. }
  15. else
  16. {
  17. callback.OnLayoutFailed(&quot;Calculations Failed!&quot;);
  18. }
  19. }
  20. private bool containsPage(PageRange[] pages,int num)
  21. {
  22. //TODO: you have to do it
  23. return true;
  24. }
  25. public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
  26. {
  27. for (int i = 0; i &lt; totalPages; i++)
  28. {
  29. // Check to see if this page is in the output range.
  30. if (containsPage(pages, i))
  31. {
  32. // If so, add it to writtenPagesArray. writtenPagesArray.size()
  33. // is used to compute the next output page index.
  34. //writtenPagesArray.append(writtenPagesArray.size(), i);
  35. PdfDocument.Page page = pdfDocument.StartPage(i);
  36. // check for cancellation
  37. if (cancellationSignal.IsCanceled)
  38. {
  39. callback.OnWriteCancelled();
  40. pdfDocument.Close();
  41. pdfDocument = null;
  42. return;
  43. }
  44. // Rendering is complete, so page can be finalized.
  45. pdfDocument.FinishPage(page);
  46. }
  47. }
  48. // Write PDF document to file
  49. try
  50. {
  51. //FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
  52. FileStream stream = new FileStream((string)destination.FileDescriptor, FileMode.Create, FileAccess.Write);
  53. pdfDocument.WriteTo(stream);
  54. }
  55. catch (Exception e)
  56. {
  57. callback.OnWriteFailed(e.ToString());
  58. return;
  59. }
  60. finally
  61. {
  62. pdfDocument.Close();
  63. pdfDocument = null;
  64. }
  65. //PageRange[] writtenPages = computeWrittenPages();
  66. /// Signal the print framework the document is complete
  67. callback.OnWriteFinished(pages);
  68. }
  69. private int computePageCount(PrintAttributes printAttributes)
  70. {
  71. int itemsPerPage = 4;
  72. MediaSize pageSize = printAttributes.GetMediaSize();
  73. if (!pageSize.IsPortrait)
  74. {
  75. itemsPerPage = 6;
  76. }
  77. int printItemCount = 1;
  78. return (int)Math.Ceiling((double)printItemCount/itemsPerPage);
  79. }
  80. }

}

  1. ### What I does
  2. 1. First I try to create seperate project with printer SDK and call to it from MAUI app. but it didn&#39;s work because policy restrictions.
  3. 2. Then I try to add printer SDK to MAUI Project. It doesn&#39;t work
  4. 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&#39;s byte array.
  5. ### What I Expecting
  6. 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);

  1. I want way to fix it?
  2. 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?
  3. google documentation have this code

writtenPagesArray.append(writtenPagesArray.size(), i);

  1. but I cant find where is coming from.
  2. </details>
  3. # 答案1
  4. **得分**: 0
  5. 实际上不想创建PrintedPdfDocument对象。我可以像这样将我的字节数组传递给文件流:
  6. ```csharp
  7. public class CustomPrintDocumentAdapter : PrintDocumentAdapter
  8. {
  9. private byte[] data;
  10. public CustomPrintDocumentAdapter(byte[] data)
  11. {
  12. this.data = data;
  13. }
  14. public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
  15. {
  16. if (cancellationSignal.IsCanceled)
  17. {
  18. callback.OnLayoutCancelled();
  19. return;
  20. }
  21. int pages = 1;
  22. if (pages &gt; 0)
  23. {
  24. PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(&quot;PDF.pdf&quot;)
  25. .SetContentType(Android.Print.PrintContentType.Document)
  26. .SetPageCount(pages)
  27. .Build();
  28. callback.OnLayoutFinished(pdi, true);
  29. }
  30. else
  31. {
  32. callback.OnLayoutFailed(&quot;Calculations Failed!&quot;);
  33. }
  34. }
  35. public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
  36. {
  37. try
  38. {
  39. FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
  40. stream.Write(data);
  41. }
  42. catch (Exception e)
  43. {
  44. callback.OnWriteFailed(e.ToString());
  45. return;
  46. }
  47. callback.OnWriteFinished(pages);
  48. }
  49. }

然后问题得以解决。

英文:

Actually Not wanted to create PrintedPdfDocument Object. I could able to pass my byte array to filestream like this

  1. public class CustomPrintDocumentAdapter : PrintDocumentAdapter
  2. {
  3. private byte[] data;
  4. public CustomPrintDocumentAdapter(byte[] data)
  5. {
  6. this.data = data;
  7. }
  8. public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
  9. {
  10. if (cancellationSignal.IsCanceled)
  11. {
  12. callback.OnLayoutCancelled();
  13. return;
  14. }
  15. int pages = 1;
  16. if (pages &gt; 0)
  17. {
  18. PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(&quot;PDF.pdf&quot;)
  19. .SetContentType(Android.Print.PrintContentType.Document)
  20. .SetPageCount(pages)
  21. .Build();
  22. callback.OnLayoutFinished(pdi, true);
  23. }
  24. else
  25. {
  26. callback.OnLayoutFailed(&quot;Calculations Failed!&quot;);
  27. }
  28. }
  29. public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)
  30. {
  31. try
  32. {
  33. FileOutputStream stream = new FileOutputStream(destination.FileDescriptor);
  34. stream.Write(data);
  35. }
  36. catch (Exception e)
  37. {
  38. callback.OnWriteFailed(e.ToString());
  39. return;
  40. }
  41. callback.OnWriteFinished(pages);
  42. }
  43. }

Then Problem get solved

huangapple
  • 本文由 发表于 2023年6月22日 17:01:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530206.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定