Java Question Need help with Samsung Galaxy Note SPen SDK

thedesolatesoul

Expert
Licensed User
Longtime User
I just wanted to add my humble observations to the discussion.

As far as I can see the SDK library wants to access some resources for the SettingsView. These are packaged within the library (JAR file).
When we try to build a b4a library, these resources are lost. Thus causing the NullPointerException.

In the SDK JAR, these are located in /resource/drawable-xhdpi/xxx.png

I dont know if there is a way to make these inbuilt resources available in B4A.

Copying these to Objects/res or Objects/resource does not work and the 9patch images seem to bomb out.
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
OK, So after the release of 2.0, Basic4Android had support for Internal handling of library files.

I've still been trying to work on this Samsung Galaxy SPen sdk and I still have no good solutions found. Here are my findings:

B4A-code
B4X:
Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim cv As RSCanvasView
   Dim sv As RSSettingView

End Sub

Sub Activity_Create(FirstTime As Boolean)
   cv.Initialize("RSCanvas")
   sv.Initialize("Setting")
   Activity.AddMenuItem("Register","mnuRegister")
   Activity.AddMenuItem("Show Pen","mnuPen")
   Activity.AddMenuItem("Hide","mnuHide")
   
End Sub

Sub mnuRegister_Click
   cv.RegisterSettingView(sv)
End Sub

Sub mnuPen_Click
   sv.showView(0)
End Sub

Sub mnuHide_Click
   sv.showView(1)
End Sub

Sub RSCanvas_Success (Success As Boolean)
   Msgbox("Registered","")
End Sub


Notes:
- RSCanvas_Success is never called
- ShowView doesn't work
- No error messages displayed.


Java CanvasView Code
B4X:
package com.rootsoft.spen;

import com.samsung.sdraw.CanvasView;
import com.samsung.sdraw.CanvasView.InitializeFinishListener;
import com.samsung.sdraw.SettingView;

import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.DontInheritEvents;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.*;
import anywheresoftware.b4a.objects.ViewWrapper;


@ShortName("RSCanvasView")
@Events(values={"Success"})
@Author("XverhelstX")
@Version(1.0f)
@ActivityObject
@DontInheritEvents
@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
@DependsOn(values = { "libspen20" })
public class CanvasViewWrapper extends ViewWrapper<CanvasView> {
   

    /**
     *    Initializes the CanvasView
     *    EventName - Name of Subs that will handle the events.
     */
    public void Initialize(final BA ba, String EventName) {
        setObject(new CanvasView(ba.activity));
        super.Initialize(ba, EventName);
        final String eventName = EventName.toLowerCase(BA.cul);
        getObject().setInitializeFinishListener(new InitializeFinishListener() {
            
            @Override
            public void onFinish() {
                // TODO Auto-generated method stub
                ba.raiseEvent(getObject(), eventName + "_success", true);
            }
            
        });
    }

    /**
     * Register the SettingView to the CanvasView.
     */
    public void RegisterSettingView(SettingView sv) {
        getObject().setSettingView(sv);
    }

}

Java Settingview Code:

B4X:
package com.rootsoft.spen;

import com.samsung.sdraw.SettingView;

import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.DontInheritEvents;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.*;
import anywheresoftware.b4a.objects.ViewWrapper;


@ShortName("RSSettingView")
@Events(values={"Success"})
@ActivityObject
@DontInheritEvents
@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
public class SettingViewWrapper extends ViewWrapper<SettingView> {
 
    /**
     *    Initializes the SettingView
     *    EventName - Name of Subs that will handle the events.
     */
    public void Initialize(final BA ba, String EventName) {
       setObject(new SettingView(ba.activity));
        super.Initialize(ba, EventName);
        final String eventName = EventName.toLowerCase(BA.cul);

    }
    
    
    
    /**
     * Control the pen or eraser functions.
     * @param tool
     */
    public void showView(int tool) {
        getObject().showView(tool);
    }
    
    /**
     * Close view
     * @param tool
     */
    public void closeView(int tool) {
        getObject().closeView();
    }


}


AVD Galaxy Note on Emulator:

START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.rootsoft.spen/.main} from pid 179


Failure taking screenshot for (230x135) to layer 21005

setKernelCountSet(10040, 1) failed with errno -2

- Start SPen App

** Activity (main) Create, isFirst = false **

setLightsOn(true)

GC_CONCURRENT freed 392K, 9% free 13017K/14151K, paused 8ms+19ms

GC_FOR_ALLOC freed 3501K, 25% free 11307K/14919K, paused 109ms

** Activity (main) Resume **

Displayed com.rootsoft.spen/.main: +5s226ms

Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@412c95e8 (uid=10009 pid=179)

setKernelCountSet(10009, 0) failed with errno -2

<--- Register pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@411daa60

<--- Show pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@412acfe0

<--- Hide pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@412e0a08

GC_CONCURRENT freed 462K, 13% free 8639K/9863K, paused 32ms+43ms

Failure taking screenshot for (230x135) to layer 21010

** Activity (main) Pause, UserClosed = true **

Acer Iconia Tab a510 & Xperia PLAY:

START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.rootsoft.spen/.main} from pid 24612


Turning on JNI app bug workarounds for target SDK version 4...


Start proc com.rootsoft.spen for activity com.rootsoft.spen/.main: pid=1520 uid=10112 gids={3003}
Flushing caches (mode 1)


setLightsOn(true)


Flushing caches (mode 0)
** Activity (main) Create, isFirst = true **


This engine isn't supported to run on this device. (brand : acer, manufacturer : Acer)


GC_FOR_ALLOC freed 230K, 5% free 6744K/7047K, paused 23ms


GC_FOR_ALLOC freed 183K, 6% free 6978K/7367K, paused 18ms


Grow heap (frag case) to 7.730MB for 904408-byte allocation


GC_CONCURRENT freed 1K, 5% free 7860K/8263K, paused 2ms+2ms


GC_FOR_ALLOC freed 180K, 5% free 8049K/8455K, paused 13ms


GC_FOR_ALLOC freed 182K, 5% free 8263K/8647K, paused 18ms


GC_CONCURRENT freed 271K, 5% free 8484K/8903K, paused 1ms+3ms


GC_CONCURRENT freed 274K, 5% free 8768K/9159K, paused 4ms+1ms


GC_CONCURRENT freed 195K, 4% free 9264K/9607K, paused 4ms+1ms


** Activity (main) Resume **


Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@417868a0 (uid=10040 pid=24612)
Displayed com.rootsoft.spen/.main: +625ms (total +21m15s279ms)

<--- Register pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4165d5a8


GC_CONCURRENT freed 670K, 56% free 8717K/19399K, paused 2ms+4ms

<--- Show pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4165b950

<--- Hide pressed --->
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@41308708


** Activity (main) Pause, UserClosed = true **


GC_FOR_ALLOC freed 2533K, 30% free 13455K/19143K, paused 37ms


GC_FOR_ALLOC freed 1273K, 29% free 13758K/19143K, paused 40ms

No longer want com.android.defcontainer (pid 853): hidden #16

i'd like to have some more input on this and any findings in the log as I'm currently stuck.

Sincerely,
Tomas
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Ok, thanks Erel.
After some little more trial and error, i figured out I had to call addView from an activity or panel. Now it is working fine, and I am adding more features to the library.

But recently, the SDK has been updated to 2.1 which changed some things in the constructor for registering the Settingscreen of the SCanvasView.

3.2. Create the SettingView

RelativeLayout canvasContainer = (RelativeLayout) findViewById(R.id.canvas_container);
mSCanvas.createSettingView(settingViewContainer, settingResourceMap, bClearAllVisibileInEraserSetting);

You can also register the SettingView to the SCanvasView as follows.

SettingView mSettingView = new SettingView(mContext, settingResourceMap);
mSCanvas.setSettingView(settingViewContainer, mSettingView, bClearAllVisibileInEraserSetting);

3.3. Then you can control the pen and eraser settings popups(SettingView) using the showSettingView() and toggleShowSettingView() functions.

mSCanvas.showSettingView(SCanvasConstants.SCANVAS_SETTINGVIEW_PEN, bShow);
mSCanvas.toggleShowSettingView(SCanvasConstants.SCANVAS_SETTINGVIEW_PEN);

4. You can start to manage the SCanvasView after finishing the SCanvasView initialization at onInitialized() of SCanvasInitializeListener.

SCanvasInitializeListener mSCanvasInitializeListener = new SCanvasInitializeListener() {
@Override
public void onInitialized() {
// Start here.
}
};
mSCanvas.setSCanvasInitializeListener (mSCanvasInitializeListener);

Now the method setSettingView is deprecated and we need to use other parameters with that function.

setSettingView
public void setSettingView(ViewGroup settingViewParent,
ViewGroup settingView,
boolean bClearAllVisibileInEraserSetting)
Sets the setting view in an S-Canvas.
Parameters:
settingViewParent - Parent layout to store the setting view
settingView - The setting view
bClearAllVisibileInEraserSetting - Whether or not to show the "Clear All" button in the eraser setting view
Since:
S-Pen SDK 2.1

Unfortunately I have no idea what parameter to give in in settingViewParent ViewGroup.

Any idea?

Tomas

EDIT:

When passing a panel as the viewgroup parameter i got the following error:

java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to anywheresoftware.b4a.BALayout$LayoutParams

B4X:
 /**
     * Register the SettingView to the CanvasView.
     */
    public void RegisterSettingView(PanelWrapper pnl, SettingView sv, boolean bClearAllVisibileInEraserSetting) {
        getObject().setSettingView(pnl.getObject(), sv, bClearAllVisibileInEraserSetting);
    }


B4X:
cv.RegisterSettingView(pnlPen, sv, True)
 
Last edited:

XverhelstX

Well-Known Member
Licensed User
Longtime User
So i'd need to change the type from a BALayout to a FrameLayout from the panel? I cannot seem to find which method to use.

Tomas

EDIT:


here the full log message as i cannot seem to find how to change the layout type
** Activity (main) Resume **


java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to anywheresoftware.b4a.BALayout$LayoutParams


at anywheresoftware.b4a.BALayout.onLayout(BALayout.java:39)
at android.view.View.layout(View.java:11283)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at anywheresoftware.b4a.BALayout.onLayout(BALayout.java:40)
at android.view.View.layout(View.java:11283)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
at android.view.View.layout(View.java:11283)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
at android.view.View.layout(View.java:11283)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
at android.view.View.layout(View.java:11283)


at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1489)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

Javadoc available here
 
Last edited:

warwound

Expert
Licensed User
Longtime User
I have now helped Tomas fix this.

The class cast and layout exceptions were a bit misleading.
Then Tomas got another exception:

java.lang.IllegalStateException: The specified child already has a parent.

It took a little while but we established that his library RSSettingView object which is passed to the library RegisterSettingView method must NOT already be added to the Activity when that method is called.

After that method has been called it is ok to add the RSSettingsView to the Activity - a B4A Panel in this case.

All fixed and working now but the original exception messages would never have helped debug the error!

Martin.
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
After some more looking, all other methods called would raise a nullpointer.

We checked if the parent was null of the view, and it was. So we meed to try how erel suggested, but we cant find out how to cast it.

Martin (warwound) and me have already broken our head on the code. I've spend a week already trying to get this to work and as we thought we had solved it, we didn't.

Samsung has launched the smartappchallenge and we want to finish this library as soon as possible so other users can participate in this challenge too.

Martin is wondering: is the method doing something to the B4A panel so it is no longer a B4A panel but an android viewgroup. when b4a tries to access the panel as a b4a panel its layout has been changed by the library method.

But we also can't seem to find on how to change the layout type as you suggested: Seems like it expects a view with a different type of LayoutParams. You can set the panel's LayoutParams to this type.

I really have no clue how i would change the panel's layout by this and I hope you would show us the code how it is done.

I would really appreciate that.

Regards, Tomas
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Do you mean create a b4a view programmaticallt and give it as a parameter viewgroup of registersettingview?

I thought a panel because its extends viewgroup.

So i cast viewgroup to the b4a view?

Tomas

Sent from my SE Xperia Play using Tapatalk.
 

thedesolatesoul

Expert
Licensed User
Longtime User
But we also can't seem to find on how to change the layout type as you suggested: Seems like it expects a view with a different type of LayoutParams. You can set the panel's LayoutParams to this type.

Have you tried pnl.GetObject().setLayoutParams
If it is expecting a FrameLayout create one.

B4X:
pnl.GetObject().setLayoutParams  = new FrameLayout.LayoutParams (int width, int height);


Why do you use a panel at all? You can create a standard view and use it instead.
I think it will be easier.
Are you saying create a new ViewGroup inside RegisterSettingView, assign it to a parent and set the layout, and then pass that to the next function?
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
I tried both these codes:

B4X:
/**
     * Register the SettingView to the CanvasView.
     */
    public void RegisterSettingView(PanelWrapper Panel, SettingView sv, boolean bClearAllVisibileInEraserSetting) {
       ViewGroup vp;
       vp = Panel.getObject();
       vp.setLayoutParams(new FrameLayout.LayoutParams (Panel.getObject().getWidth(), Panel.getObject().getHeight()));
       getObject().setSettingView(vp, sv, bClearAllVisibileInEraserSetting);
        
    }
    
    /**
     * Register the SettingView to the CanvasView.
     */
    public void RegisterSettingView2(PanelWrapper Panel, SettingView sv, boolean bClearAllVisibileInEraserSetting) {
       Panel.getObject().setLayoutParams(new FrameLayout.LayoutParams (Panel.getObject().getWidth(), Panel.getObject().getHeight()));
       getObject().setSettingView(Panel.getObject(), sv, bClearAllVisibileInEraserSetting);
        
    }

which results in a:
java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to anywheresoftware.b4a.BALayout$LayoutParams
again.

I'm gonne try the native view class now as Erel suggested.

Tomas
 
Top