Thursday, May 5, 2011

Sensors to Handle on Nexus S


So many sensors to sense!!! Hmm, I don't yet know if there are appropriate APIs available yet on Gingerbread to access all these sensors. Got to read up now.

Saturday, April 9, 2011

Using Custom fonts on Android

I had to do this for a project that I am working on, and I felt that it wasn't possible to achieve this. Well, there are several examples on the internet regarding this and nothing seemed to be working for me. So, in this post, we will see how to use custom fonts for your application on Android.

Few things before we start off:
  • Not all fonts are compatible with Android
  • You need to package the ttf files with your apk
  • It's obviously a little bit of extra work
So for this example, we have a TextView and a Button with different fonts. To be able to use your custom font everywhere, ie, on all the TextView and Button widgets in your app, you will have to extend these classes to create your own TextView and Button classes. I have named them as MyTextView and MyButton. And then, I can use these buttons in my layout xml files, with the fully-qualified name of my custom classes.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <com.beanie.samples.customfont.MyTextView
        android:layout_marginTop="10dip" android:id="@+id/textView"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="@string/hello" android:textSize="20sp"></com.beanie.samples.customfont.MyTextView>

    <com.beanie.samples.customfont.MyButton
        android:layout_marginTop="10dip" android:id="@+id/textView"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="@string/hello" android:textSize="20sp"></com.beanie.samples.customfont.MyButton>
</LinearLayout>
In both these classes, we have a method called init() which is called from all the constructors. The method is just 3 line long.
        if (!isInEditMode()) {
                  Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/ds_digib.ttf");
                  setTypeface(tf);
        }
Simple!!! You might notice that there is an if condition. This is not required, but it does help when you are preparing your layouts on eclipse, and you need to keep checking if everything's fine. This method, isInEditMode() returns true while eclipses tries to render the view from the XML.

This is what the documentation says:
Indicates whether this View is currently in edit mode. A View is usually in edit mode when displayed within a developer tool. For instance, if this View is being drawn by a visual user interface builder, this method should return true. Subclasses should check the return value of this method to provide different behaviors if their normal behavior might interfere with the host environment. For instance: the class spawns a thread in its constructor, the drawing code relies on device-specific features, etc. This method is usually checked in the drawing code of custom widgets.
If you don't put this condition, the layout editor will complain about not being able to set the TypeFace. So, in the layout editor, you will see your TextView and Button widgets with the default font. But, when you run your app on an emulator or a device, you can see the goodness of your custom fonts.

The source code for the sample project can be found here. You can find 3 different fonts (ttf file) in the assets folder to play with.

Monday, April 4, 2011

Inverted Android Button

Nothing complex. Just a few lines of code to invert your button. A horizontal flip of 180 degrees is pretty simple to achieve. If you want it with a specific angle, it might be a bit tricky.

Lets start with a creating a custom button class that extends the android Button class. Name it as InvertedButton.java.

You will need to override it's onDraw() method to rotate the canvas, so that before any drawing is done, you rotate it by 180 degrees. To make the text-alignment perfect, you will also need to do a few calculations.
    @Override
    protected void onDraw(Canvas canvas) {
        int left = getPaddingLeft();
        int top = getPaddingTop();
        int right = getPaddingRight();
        int bottom = getPaddingBottom();
        int width = getWidth() - left - right;
        int height = getHeight() - top - bottom;
       
        int saveCount = canvas.getSaveCount();
        canvas.translate(left + width / 2, top + height / 2);
        canvas.rotate(-180);
        canvas.translate((-width / 2)-left, (-height / 2)-top);
        canvas.restoreToCount(saveCount);
       
        super.onDraw(canvas);

    }
There you go. You can now add this button anywhere in your XML layouts and you will always get an inverted button.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button android:text="Button" android:id="@+id/button1"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|top" android:textStyle="bold"></Button>
    <com.beanie.examples.invertedbutton.InvertedButton
        android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom"
        android:textStyle="bold"></com.beanie.examples.invertedbutton.InvertedButton>
</LinearLayout>

You can find the source code here. Happy coding!!!!

Saturday, March 26, 2011

Websockets on Android

Have you ever tried to use Websockets on Android? In a recent project that I have been working on, it was required to use WebSockets to build a native Android app. Why a native app? Well, the current webkit that ships with the Android devices is not as fast as we would have liked. So, we had to figure out a way to build a native app that would be able to connect through WebSockets.

There are quite a few libraries available out there. And it took a bit of time to figure out the best library available. Well, the library isn't that huge. The one that we finally decided to use had only 2 java files that got our work done. Simple, isn't it?

The link to the source is here. You just need these two files:
1. WebSocket.java
2. WebSocketFactory.java

Out of these two files, the main file that you would be working on is the WebSocket.java. The WebSocketFactory.java, is just an extension of the other class that gives you WebSocket instances, based one of the two Drafts (75/76) that you request for. I am using the Draft-76 of the implementation.

For our use, we didn't require the WebView portion embedded in the source. So we removed it.
This is how you instantiate and use a WebSocket.
WebSocket webSocket = new WebSocket(URI.create("ws://yourserver.com"), DRAFT-76, "any_id");
webSocket.connect();
After you connect to the server, there are different event callbacks that you could listen for.
  1. onOpen() : This method will be called when the WebSocket is connected and ready for sending and receiving data.
  2. onClose() : This method will be called when the connection is terminated.
  3. onMessage() : This method will be called then a message is received over the socket.
  4. onError() : This method is used to notify any error message that might occur. According to the project doc on github, this currently doesn't work properly.
When you need to send a message to the server, the WebSocket class has a send method which takes in a String as the message.
webSocket.send("Your message");
 To know more about the project, visit anismiles' github project. Thanks anismiles. :)

Thursday, January 13, 2011

Android Market on Emulator (2.2)

It's been some time that I had tried getting the Market up and running on a 2.2 a.k.a Froyo emulator. On a previous post, I had described how to setup an emulator (1.5 and 1.6) with the Market app. Today, I got a comment on that post which points to a 2.2 image that does the same. You just have to download that image file and follow exactly the same steps to set it up.

This is the link to the system.img file. Thanks Anonymous for your contribution. I have tried this, and it works. Here's a link (David's Blog) that anonymous referred to. He has described all the steps to create this system image needed to put the Market app on emulator.

A few things: 
- This image will only work on a 2.2 emulator
- While creating the emulator, you should specify the cache partition size as 96 MB.

Check out the previous post for more details.

There are however a few limitations that I found with this hack.
  1. The Android Market app doesn't seem to update itself to the new UI that we currently have on our phones.
  2. There are only a limited number of apps that show up on the Market. (No Angry Birds for example)