Android Question Is possible to draw on Canvas while app is paused ?

max123

Well-Known Member
Licensed User
Longtime User
Hi all,

I've read this:
https://www.b4x.com/android/forum/threads/callsub-when-activity-paused.55533/

but I can't figure if is possible to draw on Canvas (on background) while the app stay paused.

I'm explain better here:

I've developed an app that load gcode files, parse it, draw on Canvas and then send over USB to printer controller line by line, every line wait an acknowledgment from controller "ok" before send next line.

To do this I've used an Activity (default Main activity) and wrote some classes, like Connector to connect over USB, Viewer that have a big Canvas on one panel and then all is inside a ScrollView2D to scoll it, this class shows gcode X,Y,Z movements on a canvas, and a Service that manage all app and USB, so even the data arrival (ACK from printer)

Because a USB (Connector Class) need continue to send and receive from, even if app is pauses, I've declared it on the Service, but my Viewer class I put it on the Main activity because contains some views like a Canvas.

If I switch and send app in Pause the USB continue to send and receive, but how to draw on Canvas on the same time?

What I need is not to show the Activity, but continue to draw on Canvas in background, so when I Resume the app and I see the Activity I can see the draw updated as the Activity never go in pause.

I've tried with CallSub, but because the Activity is paused, it do nothing.
I've tried CallSubDelay, but it just send some calls to a queue, and then if I resume the Activity I can't see Canvas updated.

Is there a way to do this?

Many thanks
 
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
Many thanks to all, ;);)

No @Erel , I not tried it because I still worked directly on my project that is very complex code, about 6 classes, 1 Activity and 1 Service, I need to reproduce it on a new small project and I will test your suggestion, but not really sure I've know what you explaided me.

Anyway I will try your suggestions today, maibe I recreate another project to reproduce and test it, import and use my GCodeViewer3D class.

This app, as I explained on B4X Forum, I already developed on Desktop in two versions, a version with static 3D viewer from 2D Canvas and a version with a full state of art 3D visualization using Java3d, it show a real filament in real scale and can be translated, rotated and zoomed while it simulate and even while print and draw.

The first version consumes small resources and it is very fast to parse gcode file, the second version is slow, use a lot o ram but is really 3D.

Both versions even works on Raspberry PI 3, over HDMI or on original 7 inch touchscreen and can connect USB to a printer (or CNC or Laser machine), the second one enabling a full OpenGL overlay and intalling Java3d (sudo apt-get install libjava3d-java).

The first version even works on Raspberry PI Zero W, the second one have problems due to low ram.

Using apparently the same desktop code of 2D version (first version) ported on B4A it is very slow compared to desktop version, about 300 lines every second on Nexus 7 2013, on desktop using an old single processor PC Athlon XP2600 with 1GB of ram it simulate about 7000 lines every second, all these numbers are if I do not redraw (invalidate) every line.

On both Desktop and Android I've used Regex to parse the gcode file, is the same class just adapted, the app has same classes and code logic, just adapted, on both I read a gcode file and fill a List, then I iterate from first to last list items.

Good coding...
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Hi all,

I've worked on the project this weekend and I reproduced it on small projects to know how to solve the problem.
On Test3 project there is all relevant code involved to find a solution, but here without success :(.

As you can see from my class, I initialize the ScrollView2D with very big dimensions because I need to zoom the drawings, this actually is 3500x3500 pixels, then I initialize the Canvas on ScrollView2D.Panel, this way I can scroll the canvas. As discussed with Erel I think that redraw it every line can slow down the process, not sure because not tried but already it execute slow and I need to optimize the speed execution, on my Nexus 7 2013 works 20 times slower than an old AMD Athlon XP2600 single processor PC with 1GB of ram, even I need to increase ScrollView2D panel, but it recognize max 3500x3500 pixels, if I put 3600x3600 it do not show at all, I even tried to increase Heap space on Manifest, but no, it do not show.

Another issue is that I need to scroll the ScrollView2D with this code but it do not scroll:
B4X:
mScrollPane.VerticalScrollPosition = 900
mScrollPane.Panel.Invalidate


Anyway, to stay not offtopic I've attacked 3 simple projects to reproduce that discussed on this thread:

Test1 - On this project I've tried Semen suggestions and modified a bit his code
Test2 - On this project I show how I use my viewer class to simulate 3D on 2D Canvas
Test3 - On this project I've tried to solve the problem but without success

NOTE: On Test2 scroll down manually the vertical ScrollView2D to see the drawings.

@Semen Matusovskiy your example code works well, but on the Service I need to draw with my class and I can't declare it because contains Activity objects, I can't draw on mutable bitmap without make 3D calculations that my class do. Even your code draws only while the Activity stay paused, I need to draw both, while is paused on mutable bitmap, then when it resumes draw a mutable bitmap on it and use it as start point to continue drawing on it as if app do not goes on pause state at all.

@Erel following your code example, I've tried to wrap my class to an Object on the Service (Test3) instead of a Canvas, I can see the class methods on Autocomplete, but I can't use it because the class must be initialized and require an Activity or Panel as initialization argument.
You said that I've to split my class on 2 classes, but I do not know how to do this, any sub references to Activity Objects (Canvas).
Do I need to use mutable bitmap and ImageView on it?

On Test3 project as I explained there is all relevant code, please, can you modify a bit so I can know how it works?

Many thanks for yours precious time and help, I want to put a [SOLVED] Attribute to this thread. ;)
 

Attachments

  • Test1.zip
    8.4 KB · Views: 198
  • Test2.zip
    13.4 KB · Views: 209
  • Test3.zip
    15.4 KB · Views: 191
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The answer to the main question was given in my post here: https://www.b4x.com/android/forum/t...canvas-while-app-is-paused.98552/#post-620838
That code demonstrates how you can draw while your app is in the background.

You can make ocvs a public variable and then use it from the activities as well.

You don't need any view. You draw over the mutable bitmap and you set this bitmap to be the background of any view you like.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
So I need to change my class, declare a bitmap as Global accessible from Activity and Service, initialize the Canvas as mutable bitmap and draw on it directly on my class?

And then on Service or Activity use a Global mutable bitmap as bmp.Bitmap to show it on any view background?

So I need to remove the ScrollView2D scrollable container from my class and use it on the Activity?

Yes, I've tried your code, but it draws on a Canvas without 3D calculations, so I need to move 3D calculations to the Service and draw on global mutable bitmap declared as your code in the Service?

Sorry Erel, but I am very confused because my class is involved, not just draw on bitmap. :(

Many thanks
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
The problem is that I wrote some classes to compile as library.

The library purpose is to open gcode files, parse it line by line, simulate and even control a 3D Printer or generic CNC machine over USB connection.

The classes Viewer 2D, Viewer 3D, Loader, Parser, Connector etc can be used in addictions or just as single, any class in the library is indipendent from other classes.

If in the Viewer class I put a reference to Starter.bmp, this class have dependency from Starter Service and this is no good.

This is a library that I want release in the future for B4A users. This library already works on desktop enviroment.

Many thanks
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
So I disassemble my class and put my 3D calculations on the Service, but this way I can't release my library. :(

If you see Test3 (I've prepared for you), maybe you can find the solution to this [UNRESOLVED] question.

Maybe I've to change the Thread Title to "Is possible to draw on Canvas (from another class) while app stay paused".

Many thanks for your support.
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
I quickly read the whole thread so maybe my comment is not applicable or even not useful at all..
What if you have a service that "produces" new graphics commands (line or whatever) and write them in a list; this goes the same whether the activity is paused or not.
Then the Viewer activity when resumed/active just operates on the list and draws what it needs to (everything, from point item x, last entries..).
I cannot use other lists because already I've a big list containing all file lines, up 1.000.000 of lines, this limit of file size that can be open, I think dependong on device ram, eg. on my phone I can open files max 16MB, if I open bigger the app crash, on my Nexus7 I succesfully open a 33MB file.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
This is an old thread but NOT YET SOLVED. My app now is pretty finished, the only thing is that do not work in background and it should do, or have no much sense.

My app open gcode files, can simulate these by read it line by line extrapolate XYZ coordinates and draw, the same do while control a real 3D printer over USB OTG cable and while control a 3D printer over network, here ESP32 or ESP8266 or Raspberry acts as server receiving commands and providing continue feedback to android.

The thing I want obtain is to start a print by USB or Network, switch off the screen and app continue to draw in background, send and receive data etc... until I switch the screen on to view updated datas.

It should not killed anyway from the system and should continue to work in background until user resume.

The 3D printing process can take minutes or hours.

Now that there is B4XPages something has changed, now I've the Activity app as well B4XPages app.

I've ported my very big project to B4XPages because I've read that it not paused, and some other advantages, but I don't have what I expected.

My app now can draw in background without manage it manually by code, eg. if I press Back the app will continue to work in background, even if I switch to other apps, but if the phone goes to sleep (switch off the screen) or the user switch off manually it with Power button, my app stop to work. After this if I click on app processes on it, the app simply restart by resetting all variables, all drawings etc... then crash

I already use some background services, probably this happen because my global variables are declared on the B4XPages main and not in the services ?

I cannot use a partial look because it consumes a lot of battery, already it consume much and I need to optimize. In past I'am able to do with my phone a 3D print up 6 hours, now after 2.5 hours the phone goes off, I suspect that depends on ExternalStorage that is slow and seem to drain the battery.

Now that my app works I need to do it and I search a right way to esc from this frustrating (to me) situation.
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Ok thanks Erel, I will do it.
 
Upvote 0
Top