Java Question Need help with Samsung Galaxy Note SPen SDK

XverhelstX

Well-Known Member
Licensed User
Longtime User
Hello,

I'm making a (wrapper)-library for the Samsung Galaxy Note SPen.
Samsung delivered an SDK with it, and i want to turn it into a Basic4Android compatible library.

I just need to know the basic on how I should be able to add the following:

To develop an application using the drawing function of the SDK, a canvas on which the drawing is done is required. The SDK provides the canvas through the CanvasView class included in the package.
In addition, the SDK provides the SettingView class in the package so that developers can easily register a popup layout to the CanvasView class that can be used for the pen settings.

Developers can register SettingView to CanvasView as follows.

1. Add the view to be used to the layout xml file.

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<com.samsung.sdraw.CanvasView
android:id="@+id/canvas_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<com.samsung.sdraw.SettingView
android:id="@+id/setting_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

2. Register the CanvasView and SettingView
CanvasView mCanvasView = (CanvasView) findViewById(R.id.canvas_view);
SettingView mSettingView = (SettingView) findViewById(R.id.setting_view);

1. Should I need to use a ViewWrapper? So yes, are there any Basic4Android examples
2. Can i register a CanvasView and SettingView programmatically instead of making an xml file?
3. How should i register the view then (see 2).
4. How should i be able to work with the CanvasView?
5. More things i should know?

Link to sdk: SAMSUNG Developers

Thanks,
Tomas
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
You should use ViewWrapper. I don't believe that you will need to add any XML.

Here is an example from AdMob:
B4X:
@ShortName("AdView")
@Events(values={"ReceiveAd", "FailedToReceiveAd (ErrorCode As String)",
      "AdScreenDismissed", "PresentScreen"})
@ActivityObject
@DontInheritEvents
@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
@DependsOn(values={"GoogleAdMobAdsSdk"})
public class AdViewWrapper extends ViewWrapper<AdView> {
   /**
    * 320dip x 50dip (default size)
    */
   public static Object SIZE_BANNER = AdSize.BANNER;
   /**
    * 468dip x 60dip - tablet only
    */
   public static Object SIZE_IAB_BANNER = AdSize.IAB_BANNER;
   /**
    * 728dip x 90dip - tablet only
    */
   public static Object SIZE_IAB_LEADERBOARD = AdSize.IAB_LEADERBOARD;
   /**
    * 300dip x 250dip - tablet only
    */
   public static Object SIZE_IAB_MRECT = AdSize.IAB_MRECT;
   /**
    * Initializes the AdView using the default 320dip x 50dip size.
    *EventName - Name of Subs that will handle the events.
    *PublisherId - The publisher id you received from AdMob.
    */
   public void Initialize(final BA ba, String EventName, String PublisherId) {
      Initialize2(ba, EventName, PublisherId, AdSize.BANNER);
   }
   /**
    * Initializes the AdView.
    *EventName - Name of Subs that will handle the events.
    *PublisherId - The publisher id you received from AdMob.
    *Size - One of the SIZE constants.
    */
   public void Initialize2(final BA ba, String EventName, String PublisherId, Object Size) {
      setObject(new AdView(ba.activity, (AdSize)Size, PublisherId));
      super.Initialize(ba, EventName);
      final String eventName = EventName.toLowerCase(BA.cul);
      getObject().setAdListener(new AdListener() {

         @Override
         public void onFailedToReceiveAd(Ad ad, AdRequest.ErrorCode e){
            ba.raiseEvent(getObject(), eventName + "_failedtoreceivead", e.toString());
         }
         @Override
         public void onReceiveAd(Ad ad) {
            ba.raiseEvent(getObject(), eventName + "_receivead");
         }
         @Override
         public void onDismissScreen(Ad arg0) {
            ba.raiseEventFromDifferentThread(getObject(), null, 0, eventName + "_adscreendismissed", false, null);
         }
         @Override
         public void onLeaveApplication(Ad arg0) {
            //
         }
         @Override
         public void onPresentScreen(Ad arg0) {
            ba.raiseEventFromDifferentThread(getObject(), null, 0, eventName + "_presentscreen", false, null);

         }
      });
   }

   /**
    * Sends a request to AdMob, requesting an ad.
    */
   public void LoadAd() {
      AdRequest req = new AdRequest();
      req.setTesting(true);
      
      getObject().loadAd(req);
   }

}
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Ok, great thanks Erel!

I added the CanvasView, no problems so far.
but i receive a nullpointer exception on the following:

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"})
@DependsOn(values={"libspen20"})
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.applicationContext));
        super.Initialize(ba, EventName);
        final String eventName = EventName.toLowerCase(BA.cul);

    }
    
    /**
     * Returns the settingsview.
     */
    public SettingView getObject() {
       return getObject();
    }
    
    /**
     * 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();
    }


}

Error
SettingView.Initialize("SettingView1")

java.lang.NullPointerException
at android.graphics.drawable.InsetDrawable.getChangingConfigurations(InsetDrawable.java:169)
at android.graphics.drawable.LayerDrawable.<init>(LayerDrawable.java:86)
at android.graphics.drawable.LayerDrawable.<init>(LayerDrawable.java:67)
at com.samsung.sdraw.bv.n(SourceFile:376)
at com.samsung.sdraw.bv.m(SourceFile:325)
at com.samsung.sdraw.bv.g(SourceFile:166)

This is in another class than CanvasView.

Where is the problem?

Tomas

EDIT: I'll also show you my CanvasView: There Success is not called on OnFinish, why?

i'll try onDifferentthread now.

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.applicationContext));
        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);
    }

}
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Nope still the same problem :s

Here's some more info about CanvasView and SettingView:

Package com.samsung.sdraw Description

Usage

To develop an application using the drawing function of the SDK, a canvas on which the drawing is done is required. The SDK provides the canvas through the CanvasView class included in the package.
In addition, the SDK provides the SettingView class in the package so that developers can easily register a popup layout to the CanvasView class that can be used for the pen settings.

Developers can register SettingView to CanvasView as follows.

1. Add the view to be used to the layout xml file.

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<com.samsung.sdraw.CanvasView
android:id="@+id/canvas_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<com.samsung.sdraw.SettingView
android:id="@+id/setting_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

2. Register the CanvasView and SettingView
CanvasView mCanvasView = (CanvasView) findViewById(R.id.canvas_view);
SettingView mSettingView = (SettingView) findViewById(R.id.setting_view);

3. Register the SettingView to the CanvasView
mCanvasView.setSettingView(mSettingView);

4. Then you can control the pen and eraser settings popups using
the showView() and closeView() functions provided by SettingView.


------------------------------------------------------------------------
public class SettingView
extends AbstractSettingView
This is a popup type View that allows the UI to configure the pen used to draw a figure on the CanvasView.
It inherits AbstractSettingView. The actual functions are implemented in the AbstractSettingView. The reason for the hierarchical structure design with the AbstractSettingView is to make it easy to add functions later using the abstraction methods provided by the AbstractSettingView.
Since:
S Pen SDK 1.0
Nested Class Summary

Nested classes/interfaces inherited from class com.samsung.sdraw.AbstractSettingView
AbstractSettingView.SettingChangeListener
Field Summary

Fields inherited from class com.samsung.sdraw.AbstractSettingView
ERASER_SETTING_VIEW, PEN_SETTING_VIEW, PEN_TYPE_BRUSH, PEN_TYPE_HILIGHTER, PEN_TYPE_PENCIL, PEN_TYPE_SOLID
Constructor Summary

Constructors
Constructor and Description
SettingView(Context context)
This constructor is used to construct the SettingView.
SettingView(Context context, AttributeSet attrs)
This constructor is called when the SettingView is constructed by the XML file.
SettingView(Context context, AttributeSet attrs, int defStyle)
This constructor constructs the SettingView from the XML file and applies the default style of the class.
Method Summary

Methods inherited from class com.samsung.sdraw.AbstractSettingView
closeView, isShown, isShown, setOnSettingChangeListener, showView
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Constructor Detail

SettingView
public SettingView(Context context)
This constructor is used to construct the SettingView.
It inherits the View(Context context).
Since:
S Pen SDK 1.0

Check this link out too, tutorial about the S Pen
http://innovator.samsungmobile.com/...?platformId=1&linkType=0&nacode=&codeType=All

Thanks, tomas
 
Last edited:

XverhelstX

Well-Known Member
Licensed User
Longtime User
Damn, does my code looks correct?
Do i have to upload my project?

I want to finish this quick because Samsung is launching a competition and the deadline is within 8 days.
Tomas

Sent from my SE Xperia Play using Tapatalk.

EDIT: Got the same error on the following code on settingview:

B4X:
public class SPen {
   private BA ba;
   private String eventName;
   public CanvasView mCanvasView;
   public SettingView mSettingView;
   
   /**
    * Initializes the SPen Library.
    * EventName - Events subs prefix. 
    * 
    */
   public void Initialize(final BA ba, String EventName) {
      Log.i("B4A","1");
      this.ba = ba;
      this.eventName = EventName.toLowerCase(BA.cul);
      Log.i("B4A","2");
      mCanvasView = new CanvasView(ba.applicationContext);
      Log.i("B4A","3");
      mSettingView = new SettingView(ba.applicationContext);
      
      Log.i("B4A","SPen has been initialized.");
      
   }

}

With logging, the problem is here:
setObject(new SettingView(ba.activity));
 
Last edited:

XverhelstX

Well-Known Member
Licensed User
Longtime User
Erel, Agraham or any other library developer.

In the following link you can find the documentation, project, jar file and b4a sample:

www.rootsoftllc.com/Basic4Android/SPenLibrarySDK1.0.zip

Samsung is holding a contest, and me and a friend would really want to participate. I just cannot seem to solve this.

1. The spenlib20 contains drawable-xhdpi. Is that why i receive the error?
2. Otherwise, is it possible to create a layout file like it says and make my settingsview constructor with R?

Can please anyone help me to just get this working? The contest ends within 6 days.

Tomas

EDIT:

If programmatically doesn't work, i'd like to make an xml file and work that way.
Do you have an example of working with that Erel? Or some kind of tutorial because me and TheDesolateSoul searched yesterday on how to do it and we couldn't find it. Working with R file gave us the following: R.id.settingview: settingview cannot be resolved or is not a field
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
Hello Tomas,

I have looked into your library and I don't understand why it throws a NullPointerException.

I think using layout files in B4A should be possible with the use of reflection library. As Erel said the nine patch tutorial is a good starting point to see how you can access resource files within B4A.
 

thedesolatesoul

Expert
Licensed User
Longtime User
Even I am not sure that the NullPointerException happens because the settings_view is not defined in the layout xml file. You could try constructing the settingsview purely in code (by adding it to an activity?).

But anyway, it seems like there is a difference between accessing a layout xml from an 'Android' project and a 'Java' project.

I'm sure you have already tried a lot of things already.
 

corwin42

Expert
Licensed User
Longtime User
Even I am not sure that the NullPointerException happens because the settings_view is not defined in the layout xml file. You could try constructing the settingsview purely in code (by adding it to an activity?).

The strange thing is that the NullPointerException occurs while just creating the SettingView object. Just new SettingView(ba.activity) is called and the exception is thrown. Only difference can be the context but ba.activity should be correct. I don't know what to pass else to the constructor.
 

corwin42

Expert
Licensed User
Longtime User
I think it is a bug in the Constructor of SettingView. The difference with creating the object manually and creating the object with a layout file is that another constructor is called.

In your Library you call the constructor SettingView(Context context). If the object is created from a layout file the constructor SettingView(Context context, Attributeset attrs) is called. The problem now is that AttributeSet is only an interface and there is only one implementation: The one that reads the attributes from the layout file. I have tried to manually call the constructor with the Attributeset and provided an "empty" implementation of the interface but then I get a ClassCastException. But I think that is much later. I think to use it from code you have to create a somewhat dummy implementation of a AttributeSet.

Perhaps you can write Samsung that you have found a bug in their SDK. :)
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Thanks corwin,

I had already send them a email yesterday and even opened a topic on the discussion tab. They both ignored me on the email and the discussion.
I think it's because it's B4A related (?) that they don't know the answer.

I think you might know the problem further than i do, so i'd ask if you could send them an email with the bug report?

If you have technical questions about the S Pen SDK you can email [email protected] and you can post questions on the Discussions tab.

Could you also upload your project file of eclipse so i can see how you worked with the R, xml, etc.

Thanks
Tomas
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Damn. :s

I copied the drawable-hdpi to my res folder, readonly and when i compile i got the following error message:

Compiling generated Java code. 3.55
Convert byte code - optimized dex. 0.66
Packaging files. Error
ERROR: 9-patch image res\drawable-xhdpi\eraser_bar.9.png malformed.
Frame pixels must be either solid or transparent (not intermediate alphas).
Found at pixel #8 along top edge.
ERROR: Failure processing PNG image res\drawable-xhdpi\eraser_bar.9.png
ERROR: 9-patch image res\drawable-xhdpi\image_bg.9.png malformed.
Must have one-pixel frame that is either transparent or white.
ERROR: Failure processing PNG image res\drawable-xhdpi\image_bg.9.png

any help on that? :s or reflection code or something?

Tomas
 
Top