Tuesday, February 28, 2012

Native Theming

One of the things people asked about the MWC application is how did we get the native theme to apply to the different platforms. The answer is quite simple: when you create a new theme In the Codename One designer the first option is: "Native Theme".

When you look at this theme it seems empty however it assumes the iOS look by default. You can change the "native preview" by selecting the "Native Theme" menu in the menu bar and selecting the OS. You can pick an arbitrary native theme which can be used when targeting J2ME where no "actual" native theme exists.

This allows you to preview how your UI will look in different platforms and adapt the theme to make the appearance fit a different platform aesthetics.

The old themes that don't "derive" from the native look and feel are all there, the thing that makes this theme "special" is the "includeNativeBool" flag which automatically injects the native OS theme before loading this theme. This allows us to "override" or add UIID's for various platforms.

You can also add a platform override to a specific theme: by selecting the "Override In Platform" combo box and pointing it to the platform in which you need something different. E.g. override icons for a specific platform.
There is currently a bug on this that is reproducible only on one machine (and doesn't reproduce with the debugger) so I won't go too much into the details of this feature for now.

Wednesday, February 22, 2012

MWC Events Guide Application

We've been working with the Israel Mobile Summit on their annual MWC event guide application & we are pretty pleased to announce its availability on all major platforms.

The application features an offline guide to the Mobile World Congress events and includes native device themes and integration. It was built entirely using the Codename One environment and is available for RIM/Android/iOS & J2ME.

You can download it right now from iTunes, Android Market & Get JAR (J2ME/RIM) versions. (Update: if the J2ME link isn't working for you try this link).

While the application is relatively simple it does show the power of Codename One and what it can achieve with mobile device development.

On a related note we decided to accelerate the private beta phase. We will send out the private beta to the final batch of beta testers during this weekend or early next week. We are tentatively planning a quiet launch of the public beta for the first week of March.

Sunday, February 12, 2012

Going "Native"

Codename One takes on a lofty goal: making platforms that are radically different in every way (even in their underlying programming language) act as one. We achieved that thanks to the power of Java, but its not enough...

We wanted to give developers the ability to go into the native platform to workaround any missing functionality. Obviously going to the native platform raises the level of complexity for a platform but we wanted to keep native access as simple and powerful as can be.

But first a recap on how Codename One works...
When developing on Codename One you build an application with our simulator, when you want to test on a device the build is sent to the server which generates the platform specific code. This simplified one of the hardest concepts within LWUIT and brought Codename One into the league of desktop development tools in terms of ease of use.

A question that keeps popping up is "do I need to use the build server". The answer is no but you probably would. The build server is free for use (within reasonable quotas) you could download the  various platform native ports and manually build like you did in LWUIT but this will be even harder since you will need a far more elaborate build toolchain and you will need a Mac (for iOS build) and a Windows 7 machine (for Windows Phone 7)... That's obviously a pain most of you would want to avoid.

So how would the build server allow developers to access the "native" layer (and why do I quote "native"?).
When defining "native" we set out to build something that allows access to the "true" platform specifically Dalvik on Android, MIDP+JSR's on J2ME, RIM API on Blackberry, Objective C on iOS and C# on Windows Phone 7. Hence "native" is not used in the common historical reference to C but more as the common underlying platform.

In order to unify such disparate platforms we made some restrictions which we might reduce in the future but for now all you need to do is define an interface that derives native interface e.g.:

public interface MyNativeCall extends NativeInterface {
     public String sayHello();
}

You can right click the native interface in NetBeans and it will generate stubs for all the native platforms within a directory called "native" under the project root. To access the native interface instance all you need to do is something like this:
        try {
            MyNativeCall n = (MyNativeCall)NativeLookup.create(MyNativeCall.class);
            if(n != null && n.isSupported()) {
                String s = n.sayHello();
                System.out.println("Native says: " + s);
            } else {
                System.out.println("Native interface is not supported on this platform");
            }
        } catch(Throwable t) {
            Dialog.show("Error", "Exception during native access: " + t, "OK", null);
        }

Notice several things about this example:
  • You don't need to implement the native interface, the server implements the "glue code" to generate the call to the native code.
  • The native interface has an isSupported() method that you need to implement in the native stub (more on that soon).
When building for device the source for the native code is sent together with the application jar to the server. We need to send the source for the native call since native compilation requires a rather complex toolchain (e.g. Android, xcode etc.).

I can go into all the various platform specific stubs but that is superfluous so I'll focus on Android/Dalvik which most readers should find familiar. The native stub generated for Android would look something like this:
public class MyNativeCallImpl {
     public boolean isSupported() {
          return false;
     }
     public String sayHello() {
          return null;
     }
}

Notice that the code DOES NOT implement the MyNativeCall interface (more on that soon). Just edit the generated code to this:
public class MyNativeCallImpl {
     public boolean isSupported() {
          return true;

     }
     public String sayHello() {
          return "Hello";

     }

}


And you will have your native interface working on Android. Your native interface implementation can callback into your application and reference static variables in your code. You will however, be limited by the type of variables you can transfer in order to make the code easily portable to Objective C/C (more on that in the JavaDoc's).


The reason the native implementation class doesn't implement the interface is its support for PeerComponent which allows embedding a native Component "in-place'. We have a demo in the distribution (appropriately called native demo), that demonstrates just that. When returning a peer component your interface will look like this:


public interface NativeCalls extends NativeInterface {
    public PeerComponent createNativeButton(String title);
}

And your native impl will look like this:
public class NativeCallsImpl {
    public android.view.View createNativeButton(String param) {
        android.widget.Button b = new android.widget.Button((android.content.Context)NativeDemo.getContext());
        b.setText(param);
        return b;
    }
}


Notice that the native implementation returns a platform specific UI component which is seamlessly translated to a peer component. For the thrill seekers among you here is how this code looks in Objective C, header file:
#import

@interface com_codename1_nativedemo_NativeCallsImpl : NSObject {
}

-(void*)createNativeButton:(NSString*)param;
-(BOOL)isSupported;
@end






And implementation file:
#import "com_codename1_nativedemo_NativeCallsImpl.h"
#import

@implementation com_codename1_nativedemo_NativeCallsImpl

-(void*)createNativeButton:(NSString*)param{
    UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [myButton setTitle:param forState:UIControlStateNormal];
    return myButton;
}


-(BOOL)isSupported{
    return YES;
}

@end


Wednesday, February 8, 2012

Busy Couple Of Weeks

Please forgive me for not making a more substantive post this week. I am spending most of this week and half of next week in a training program and won't have quite the same amount of time for doing everything else I normally do during the week.
We will however send out an additional batch of invites for 10 people this time to get into the beta round.

I promise to provide more updates and tutorials when I finish this round of the workshop.
As a side note, I copied the hello world tutorial into the website and also added a signing tutorial and a discussion group. Please check them out a http://www.codenameone.com/ and let us know what you think.

Friday, February 3, 2012

Codename One Private Beta Is Now Officially Live!

We are now live for the first batch of Codename One beta testers who should receive the instructions to getting started with the initial beta via an email we just sent out.

If you signed up to the beta you should have gotten an email from us on 13 Jan 2012 titled "Welcome To Codename One Private Beta Group" or "A Message From Codename One". If you got neither you need to check your spam folder and let us know of an alternative email we can use via the feedback section in the Codename One site or here in the comments.

As part of that we have opened a Google discussion group for Codename One here. You can follow the discussion right away.

We are tiering the beta which means we are slowly adding people to the service both to see the load on our servers and to get a fresh perspective every time. If you were accepted to the beta and only got the first welcome email that's OK you will get another email sometime in February/early March with the full details for downloading Codename One.

We ask that you don't distribute these beta's until our servers are ready to cope with the loads.