Android Question Cloud printing margins

MitchBu

Well-Known Member
Licensed User
Thanks to this forum help, I have now been able to silently generate a picture, to load it later in a WebView and print it with CreatePrinterAttributes and CreateWebPrintJob as described by Erel here :
https://www.b4x.com/android/forum/threads/android-printing-framework.38796/page-2#post-247461

It works fine, but I need to adjust the margins. Top margin is slightly over an inch, left and right margins are 1/2 inch. That is much too much for what I want to do.

Would it be possible in createprinterattribute to set the margins ?

B4X:
Sub CreatePrinterAttributes As JavaObject
   Dim builder As JavaObject
   builder.InitializeNewInstance("android.print.PrintAttributes.Builder", Null)
   Dim mediaSize As JavaObject
   mediaSize = mediaSize.InitializeStatic("android.print.PrintAttributes.MediaSize").GetField("ISO_A6")
   Return builder.RunMethod("build", Null)
End Sub

I found this
https://developer.android.com/reference/android/print/PrintAttributes.Margins.html
but am a bit lost about how to apply it.
 
Last edited:

MitchBu

Well-Known Member
Licensed User
Exploring, I have been able to come up with "no_margin", but it does nothing more than the previous code.

What I need to understand is how to instanciate a new setting for each margin. All I tried crashed.

It seems what would be necessary is the constructor with apparently margins in mils

But I don't know enough Java to create the proper code.

PrintAttributes.Margins(int leftMils, int topMils, int rightMils, int bottomMils)

This is what I have now :

B4X:
Sub CreatePrinterAttributes As JavaObject
   Dim builder As JavaObject
   builder.InitializeNewInstance("android.print.PrintAttributes.Builder", Null)
   Dim mediaSize As JavaObject
   mediaSize = mediaSize.InitializeStatic("android.print.PrintAttributes.MediaSize").GetField("ISO_A6")
   Dim margins As JavaObject
   margins = margins.InitializeStatic("android.print.PrintAttributes.Margins").GetField("NO_MARGINS")
   Return builder.RunMethod("build", Null)
End Sub
 
Last edited:
Upvote 0

MitchBu

Well-Known Member
Licensed User
I did this :
B4X:
   Dim margins(4) As Int
   margins(0) = 50
   margins(1) = 50
   margins(2) = 50
   margins(3) = 50
   builder.RunMethodJO("setMediaSize", Array (mediaSize)).RunMethodJO("setMinMargins", Array(margins))
   Return builder.RunMethod("build", Null)

But no joy :

Error occurred on line: 94 (Main)
java.lang.RuntimeException: Method: setMinMargins not matched.
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:129)
at anywheresoftware.b4j.object.JavaObject.RunMethodJO(JavaObject.java:138)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:753)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:343)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:259)
at b4a.canvas.main._createprinterattributes(main.java:505)
at b4a.canvas.main._button1_click(main.java:494)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:708)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:340)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
at android.view.View.performClick(View.java:5214)
at android.view.View$PerformClick.run(View.java:20978)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6134)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

** Activity (main) Pause, UserClosed = true **
** Activity (main) Resume **
** Service (starter) Destroy **
 
Upvote 0

MitchBu

Well-Known Member
Licensed User
After much reading on the forum, to better understand the calling structure, I tried this, but got the same error message :
B4X:
builder.RunMethodJO("setMediaSize", Array (mediaSize)).RunMethodJO("setMinMargins", Array(1200, 1200, 1200, 1200))

Also, I am starting to wonder if I am using the right method.

Printing from Gallery there are very small margins. So there must be another method that does not impose very large margins.
 
Upvote 0

DonManfred

Expert
Licensed User
are you sure you want to have marginswith a MINIMUM of 1200?
I would try to set themto a MUCH MUCH smalller value. Maybe try to use 0 or 1 or so...
 
Upvote 0

MitchBu

Well-Known Member
Licensed User
Upvote 0

Erel

Administrator
Staff member
Licensed User
It should be:

B4X:
Sub CreatePrinterAttributes As JavaObject
   Dim builder As JavaObject
   builder.InitializeNewInstance("android.print.PrintAttributes.Builder", Null)
   Dim mediaSize As JavaObject
   mediaSize = mediaSize.InitializeStatic("android.print.PrintAttributes.MediaSize").GetField("ISO_A6")
   Dim margins As JavaObject
   margins = margins.InitializeStatic("android.print.PrintAttributes.Margins").GetField("NO_MARGINS")
builder.RunMethodJO("setMediaSize", Array (mediaSize)).RunMethodJO("setMinMargins", Array(margins))
Return builder.RunMethod("build", Null)
End Sub
 
Upvote 0

MitchBu

Well-Known Member
Licensed User
Erel, I appreciate your assistance.
Now, and this is absolutely not your fault, it seems setMinMargin works on top of existing margins, and does not allow setting smaller margins than the default.

Back to the drawing board.

What about android.support.v4.print described at
https://developer.android.com/reference/android/support/v4/print/package-summary.html

It seems relatively simple, and it has a property for setting the scale :

setScaleMode(int scaleMode)
Selects whether the image will fill the paper and be cropped SCALE_MODE_FIT
or whether the image will be scaled but leave white space
SCALE_MODE_FILL.

Could this be implemented in B4A ?
 
Last edited:
Upvote 0

Erel

Administrator
Staff member
Licensed User
1.
B4X:
#AdditionalJar: com.android.support:support-v4

2.
B4X:
Sub PrintBitmap (bmp As Bitmap)
   Dim ctxt As JavaObject
   ctxt.InitializeContext
   Dim photoPrinter As JavaObject
   photoPrinter.InitializeNewInstance("android.support.v4.print.PrintHelper", Array(ctxt))
   If photoPrinter.RunMethod("systemSupportsPrint", Null) = True Then
     'FIT = 1, FILL = 2
     photoPrinter.RunMethod("setScaleMode", Array(1))
     photoPrinter.RunMethod("printBitmap", Array("Printer Job Name", _
       bmp, Null))
   Else
     Log("Printing not supported.")
   End If
End Sub

3.
B4X:
PrintBitmap(LoadBitmap(File.DirAssets, "MyBitmap.png"))
 
Upvote 0

MitchBu

Well-Known Member
Licensed User
Hi Erel. I copied this to my project, and placed this in #Region Activity Attributes :
B4X:
#AdditionalJar: com.android.support:support-v4

But when I try to run, I get :
Organizing libraries. Error
Maven artifact not found: com.android.support/support-v4
 
Upvote 0

MitchBu

Well-Known Member
Licensed User
Mazeltov :)

Now I finally got a no left margin printing. For some reason, there is still a 7/16th" top margin (12 mm) on the HP Envy 100 T410. On an USB ePrint HP P1005 attached to my Mac I have added to Cloud Print, printing is almost entirely borderless, with a 1/8th inch on top (4 mm).

Now I can continue work on an Android app that I know will print correctly.

The only drawback is the time it takes between sending the job to Cloud Print, and the actual printing : some like a full minute. But I guess this is unavoidable.
 
Last edited:
Upvote 0

Erel

Administrator
Staff member
Licensed User
Note that you can add a listener that will be raised when the job finishes.

Something like:
B4X:
Sub PrintBitmap (bmp As Bitmap)
  Dim ctxt As JavaObject
  ctxt.InitializeContext
  Dim photoPrinter As JavaObject
  photoPrinter.InitializeNewInstance("android.support.v4.print.PrintHelper", Array(ctxt))
  If photoPrinter.RunMethod("systemSupportsPrint", Null) = True Then
  'FIT = 1, FILL = 2
  photoPrinter.RunMethod("setScaleMode", Array(1))
    Dim ev As Object = photoPrinter.CreateEventFromUI("android.support.v4.print.PrintHelper.OnPrintFinishCallback", "finish", Null)
  photoPrinter.RunMethod("printBitmap", Array("Printer Job Name", _
  bmp, ev))
  Else
  Log("Printing not supported.")
  End If
End Sub

Sub finish_Event (MethodName As String, Args() As Object) As Object
   Log("Finished!")
   Return Null
End Sub
It will only work if the event fires after the activity has resumed. You can move it to a service if this is an issue.
 
Upvote 0
Top