Android Question [B4XPAges] java.lang.RuntimeException: Method: takeScreenshot not found in: com.ISS.DC1X.main

MrKim

Well-Known Member
Licensed User
Longtime User
A line similar to this works fine in a B4A only App (https://www.b4x.com/android/forum/threads/take-a-screenshot-with-inline-java-code.86798/#content)
B4X:
JobDataScrlLblIMGV.Bitmap = Main.NativeMe.RunMethod("takeScreenshot", Array(Main.NativeMe))
But trying to run it in a B4XPages app elicits the error in the title.
I tried running the line (modified for Main) in Main (thinking that might be the issue) with the same result.

I will tell you what I am trying to accomplish. I like the BBScrollingLabel but sometimes I want to freeze it so I can read it. Since there is no way to stop it I thought I would screen shot it and put it in a B4XImageview right over the top. Giving the appearance of freezing it.

Any help appreciated.
 
Solution
Just a simple idea... Based on the original sample of BBScrollingLabel, why not attach the Label to a panel (as B4XView) and use the Snapshot method?

See attached a working sample.

label.gif


B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private ImageView1 As ImageView
  
    Private BBScrollingLabel1 As BBScrollingLabel
    Private TextEngine As BCTextEngine
    Private Panel1 As B4XView
    Dim t As Timer
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    TextEngine.Initialize(Root) 'change to...

MrKim

Well-Known Member
Licensed User
Longtime User
There IS NO USEFUL INFORMATION IN THIS POST. No code, no full error!
How should one help?

Upload a small example showing the problem.- Do not expect others are doing an example
Will do. I thought perhaps there was an obvious solution that I was missing. I did provide the offending line of code.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I did provide the offending line of code.
Context is important. Even that one line of code relies on a JavaObject whose declaration you have not given. Referring to code in another post is not always good enough, it is your actual code that is executing that matters. People make typos transcribing code so seeing the actual code is important. This is why a small example that demonstrates the problem is so useful.
 
Upvote 0

MrKim

Well-Known Member
Licensed User
Longtime User
I have GOT to stop posting when it is late and I am tired. I did not include the inline Java code when I copied the code from the link listed above:
Java:
#If Java

import android.app.Activity;
import android.graphics.Bitmap;
import android.view.ViewGroup;

public static Bitmap takeScreenshot2(Activity activity) {
        ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
        ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
        decorChild.setDrawingCacheEnabled(true);
        decorChild.buildDrawingCache();
        Bitmap drawingCache = decorChild.getDrawingCache(true);
        Bitmap bitmap = Bitmap.createBitmap(d rawingCache);
        decorChild.setDrawingCacheEnabled(false);
        return bitmap;
}

#End If
But that brought up a new set of errors which I was finally able to resolve. But only worked in main. But eventually I was able to make it work in a standalone routine. I have posted a project which works, but also has a bunch of commented code some which also works. The relevant code is this:
B4X:
    Dim NM As JavaObject
    NM.InitializeContext
    Dim MENM As JavaObject = Me
    B4XImageView1.Bitmap = MENM.RunMethod("takeScreenshot2", Array(NM))
Took me a lot of monkeys and typewriters work to figure this out. Hopefully someday someone can explain to me what .InitializeContext gets you vs Me.

The ME came from one of Erel's examples showing how to run java code from a Class Module"
B4X:
'Class module
Sub Class_Globals
    Private nativeMe As JavaObject
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    nativeMe = Me
    Log(nativeMe.RunMethod("Multiply", Array (10)))
End Sub

#If JAVA
private int mm = 100;
public int Multiply(int i) {
    return i * 2 + mm;
}
#End If
But of course this did not work for me because the array needed to be a javaobject, not a number and needed to be .InitializeContext , not Me.

I'm also not sure if what I did is legal and reliable. All the examples I find have the java object in Process_Globals and the .initializecontext or = Me in Activity_Create or Initialize. I moved these into my Sub because that is the only place I need them. I also don't understand why if run from Main this works:

B4X:
Sub Globals
    Private  nativeMe As JavaObject
 
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim pm As B4XPagesManager
    pm.Initialize(Activity)
    If FirstTime Then
        nativeMe.InitializeContext
    End If
End Sub
.
.
.
Public Sub Screenshot(B4XImgV As B4XImageView)
        B4XImageView1.Bitmap = nativeMe.RunMethod("takeScreenshot", Array(nativeMe))
End Sub
That is nativeMe.....nativeMe but when running it from MainPage RunMethod needs to be JavaObject = Me and the Array needs to be JavaObject.InitializeContext.


Just because it is what I was after I threw in the code to crop the screenshot to a specific control, which is what I was after:
B4X:
    Dim Dims(2) As Int
    Dim B As JavaObject = Button1
    B.RunMethod("getLocationOnScreen", Array As Object(Dims))
    B4XImageView1.Bitmap = B4XImageView1.Bitmap.Crop(Dims(0), Dims(1), Button1.Width, Button1.Height)
    B4XImageView1.ResizeMode = "FILL_NO_DISTORTIONS"
Now, "getLocationOnScreen" is, evidently, Java code that is built in to the control? Go figure. No inline code required.

Anyway, thanks for your help. A program that works is attached. At least I hope it works, I posted this when it is late and I am tired ?? ?
 

Attachments

  • TakeScreenShotTest.zip
    15.8 KB · Views: 156
Last edited:
Upvote 0

josejad

Expert
Licensed User
Longtime User
Just a simple idea... Based on the original sample of BBScrollingLabel, why not attach the Label to a panel (as B4XView) and use the Snapshot method?

See attached a working sample.

label.gif


B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private ImageView1 As ImageView
  
    Private BBScrollingLabel1 As BBScrollingLabel
    Private TextEngine As BCTextEngine
    Private Panel1 As B4XView
    Dim t As Timer
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    TextEngine.Initialize(Root) 'change to Form.RootPane in B4J or Page.RootPanel in B4i
    BBScrollingLabel1.TextEngine = TextEngine
    BBScrollingLabel1.Text = $"[b][u]BBScrollingLabel[/u][/b]: [color=red]Red[/color] [color=0xFF08B31F]Green[/color] [color=blue]Blue[/color]. More information: [url]https://www.b4x.com[/url]..............."$
    t.Initialize("Timer1", 1000)
    t.Enabled = True

End Sub



Sub Timer1_Tick
    'Handle tick events
    Log("Tick")
    ImageView1.Bitmap = Panel1.Snapshot
End Sub
 

Attachments

  • BBCode.zip
    14.4 KB · Views: 139
Last edited:
Upvote 0
Solution

MrKim

Well-Known Member
Licensed User
Longtime User
Just a simple idea... Based on the original sample of BBScrollingLabel, why not attach the Label to a panel (as B4XView) and use the Snapshot method?
Laugh 'till I cry ? ? . I spent 2 days screwing around with this and you solved it with one line of code. Actually already had it on a pane to set the background color so.
B4X:
        JobDataScrlLblIMGV.Bitmap = JobDataScrlLblPane.Snapshot
Solved it.
You know that's the problem when you have a lousy memory. I started with your idea three days ago but the B4A controls I looked at didn't have a snapshot where I used snapshot extensively was in a B4J only app and so I was thinking that must be a B4J only property. I should have looked more closely.

Oh well, I learned a lot.

Aaaand this post will explain to all why my projects take so long to complete!
 
Upvote 0

josejad

Expert
Licensed User
Longtime User
If its 5:40AM where you are, it's fine to go to bed.... glad to help you
 
Upvote 0

josejad

Expert
Licensed User
Longtime User
I thought you were in California
 
Upvote 0

Mariano Ismael Castro

Active Member
Licensed User
Hi, this seems to work fine on B4XPages (tested with Android 7). I attach the project
Based on this https://www.b4x.com/android/forum/threads/take-a-screenshot-with-inline-java-code.86798/post-549521

TakeScreenShot:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private ImageView1 As ImageView
End Sub

Public Sub Initialize
    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Private Sub Button1_Click
'    xui.MsgboxAsync("Hello world!", "B4X")
    ImageView1.Bitmap=TakeScreenshot
End Sub

'https://www.b4x.com/android/forum/threads/take-a-screenshot-with-inline-java-code.86798/post-549521
Private Sub TakeScreenshot As Bitmap
    Dim jo As JavaObject
    jo.InitializeContext
    
    Dim decor As JavaObject = jo.RunMethodJO("getWindow", Null).RunMethod("getDecorView", Null)
    Dim decorChild As JavaObject = decor.RunMethod("getChildAt", Array(0))
    decorChild.RunMethod("setDrawingCacheEnabled", Array(True))
    decorChild.RunMethod("buildDrawingCache", Null)
    Dim bmp As Bitmap = decorChild.RunMethod("getDrawingCache", Array(True))
    bmp.Initialize3(bmp)
    decorChild.RunMethod("setDrawingCacheEnabled", Array(False))
    Return bmp
End Sub
 

Attachments

  • TakeScreenshot.zip
    14.3 KB · Views: 150
Upvote 0
Top