Android Question Return Text of each line by reflection lib

ArminKH

Well-Known Member
Hi all
I want to return the text of each line in a view(like label) by using reflection library.(i can do this by while--loop and some calculation but looking for a faster way to do it)
Pls help me to find out the best method of doing this just by reflection library
 
Last edited:

stevel05

Expert
Licensed User
Longtime User
Why must you use the reflection library? The easiest way is to use Regex.Split. Split the text on CRLF and you end up with an array with one line per index.
B4X:
Dim Lines() As String = Regex.Split(CRLF,Label.Text)
 
Upvote 0

ArminKH

Well-Known Member
Why must you use the reflection library? The easiest way is to use Regex.Split. Split the text on CRLF and you end up with an array with one line per index.
B4X:
Dim Lines() As String = Regex.Split(CRLF,Label.Text)
Because each line is not finished by a crlf
Maybe your way is true just to find paragraphes
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
OK understood, an interesting one. Try this:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.


    Private Label1 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("1")

    Label1.Text = "test of extractable text, see if we can get single lines"
    CallSubDelayed(Me,"DoMeasure")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub DoMeasure
    Dim Lines() As String = GetText(Label1)
    Log("No Lines " & Lines.Length)
    For Each S As String In Lines
        Log(S)
    Next
End Sub
Sub GetText(Source As JavaObject) As String()

    Dim Text As String = source.RunMethod("getText",Null)

    Dim Layout As JavaObject

    Dim LineCount As Int = Source.RunMethod("getLineCount",Null)
    Dim Lines(LineCount) As String

    Layout = Source.RunMethod("getLayout",Null)

    Dim Start,LineEnd As Int
    Start = 0
    For i = 0 To LineCount - 1
        LineEnd = Layout.RunMethod("getLineEnd",Array(i))
        Lines(i) = Text.SubString2(Start,LineEnd)
        Start = LineEnd
    Next
    Return Lines
End Sub

CallSubDelayed is used as it is not possible to interrogate the layout while it is being created.

You just need to create a Layout in the designer with an EditText1 and load it. It also works with labels.

Based on code found here: http://stackoverflow.com/questions/9325798/android-textview-and-getting-line-of-text
 
Last edited:
Upvote 0

ArminKH

Well-Known Member
OK understood, an interesting one. Try this:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.


    Private Label1 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("1")

    Label1.Text = "test of extractable text, see if we can get single lines"
    CallSubDelayed(Me,"DoMeasure")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub DoMeasure
    Dim Lines() As String = GetText(Label1)
    Log("No Lines " & Lines.Length)
    For Each S As String In Lines
        Log(S)
    Next
End Sub
Sub GetText(Source As JavaObject) As String()

    Dim Text As String = source.RunMethod("getText",Null)

    Dim Layout As JavaObject

    Dim LineCount As Int = Source.RunMethod("getLineCount",Null)
    Dim Lines(LineCount) As String

    Layout = Source.RunMethod("getLayout",Null)

    Dim Start,LineEnd As Int
    Start = 0
    For i = 0 To LineCount - 1
        LineEnd = Layout.RunMethod("getLineEnd",Array(i))
        Lines(i) = Text.SubString2(Start,LineEnd)
        Start = LineEnd
    Next
    Return Lines
End Sub

CallSubDelayed is used as it is not possible to interrogate the layout while it is being created.

You just need to create a Layout in the designer with an EditText1 and load it. It also works with labels.

Based on code found here: http://stackoverflow.com/questions/9325798/android-textview-and-getting-line-of-text
this is exactly the best answer to my question
Thank :)
The javaobject lib has not any method for access to text of each line directly?liked "getLineText"???
And in where page i can see all methods of reflection or javaobject? I think the methods are secret for beginners :)
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
JavaObject, like reflection, only has methods that allow it to be used as a gateway to access other methods that are in Java. With it you can access a large percentage of the underlying Java methods. So you need to have an idea of what you want to achieve, find some Java code that does what you want, then set about finding out how to access it through JavaObject or Reflection.
 
Upvote 0

ArminKH

Well-Known Member
JavaObject, like reflection, only has methods that allow it to be used as a gateway to access other methods that are in Java. With it you can access a large percentage of the underlying Java methods. So you need to have an idea of what you want to achieve, find some Java code that does what you want, then set about finding out how to access it through JavaObject or Reflection.
Ok understood
Tnx again 4 your quick response mr estevel :)
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Since @stevel05 clever code is intended to break a label into several lines, I added a small code to it to accommodate the height of the label and show all the text once the label is broken up into multilines:
B4X:
Dim StrUtils As StringUtils  'in Globals . Require StringUtils Lib

CallSubDelayed("","SetTextHeight")   ' In Activity_Create  below CallSubDelayed(Me,"DoMeasure")

Sub SetTextHeight
    Label1.Height = StrUtils.MeasureMultilineTextHeight(Label1, Label1.Text)
End Sub
 
Upvote 0

ArminKH

Well-Known Member
@stevel05
Can u please edit above codes and convert that to reflection library?
Because my app crashed(force close) on android 2.1 and 2.3
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
What error are you getting? There is no point in converting a java library to Reflection, it will have the same result. Sorry, I don't have a 2.1 device to test it on.
 
Upvote 0

ArminKH

Well-Known Member
please see attached project
all things are okay on android above 3 , but on android 2.1 and 2.3 the error is"java.lang.reflect.InvocationTargetException"
please test it on emulator
 

Attachments

  • P.zip
    12.5 KB · Views: 201
Upvote 0

ArminKH

Well-Known Member
full error is

java.lang.reflect.InvocationTargetException


at android.text.StaticLayout.getLineStart(StaticLayout.java:1203)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:130)
at b4a.example.main._save(main.java:479)
at b4a.example.main._button1_click(main.java:395)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:77)
at android.view.View.performClick(View.java:2364)
at android.view.View.onTouchEvent(View.java:4179)
at android.widget.TextView.onTouchEvent(TextView.java:6541)
at android.view.View.dispatchTouchEvent(View.java:3709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
at android.app.Activity.dispatchTouchEvent(Activity.java:2061)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1691)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ArrayIndexOutOfBoundsException
... 33 more
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
The error is
Caused by: java.lang.ArrayIndexOutOfBoundsException
 
Upvote 0

ArminKH

Well-Known Member
The error is
Caused by: java.lang.ArrayIndexOutOfBoundsException
ok this error happen because java object not return any value on android 2.1
what is the solution?please see attached project
every thing is perfect on +3 android devices
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Have you tried this on a real device? I had a 2.1 test device on the emulator ( which I don't use anymore as it's slow and inconsistent), it has a problem getting the text length, it is returned as a silly figure: 1136198696

Try putting:
Log(Text.Length)

After the call to getText. It's the same if you call Label1.Text.Length.

After changing the calls to use reflection, If I then run an Android 3 device in the emulator and run the app on there it works, if I then run it on the 2 device while the 3 device is still loaded, it works.

Bottom line: Try it on a real device!
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
If you want to try it the code with reflection is:

B4X:
Private Sub Save
    Dim Source=Label1 As JavaObject
    Dim Text As String=Source.RunMethod("getText",Null)
    Dim Layout As JavaObject=Source.RunMethod("getLayout",Null)
    Dim LineCount As Int=Source.RunMethod("getLineCount",Null)
    Dim TextByLine(LineCount) As String

    Dim LineStart,LineEnd As Int
    Log(Layout.RunMethod("getLineCount",Null))
    Dim R As Reflector
    R.Target = Layout
        Dim A As Int
        For A=0 To LineCount - 1
            LineStart=R.RunMethod2("getLineStart",A,"java.lang.int")'Layout.RunMethod("getLineStart",Array As Object(A))
            LineEnd=R.RunMethod2("getLineEnd",A,"java.lang.int")'Layout.RunMethod("getLineEnd",Array As Object(A))
            TextByLine(A)=Text.SubString2(LineStart,LineEnd).Trim
            Log(TextByLine(A))
        Next
        Log(LineCount)
End Sub
 
Upvote 0
Top