Saturday, December 31, 2011

i-muz Tx72 7" inch android tablet

Recently I purchased iMuz Tx72 7" inch android tablet. I wanted a tablet on which I can read book and browse internet and this tablet full fill both that requirement quite well.

I went for this tablet as other similar config tablet like Kindle Fire or Nook are not easily available here or available but need to pay extra price. This was easily available for me, placed order online on gmakret and got it next day.

Currently it comes with android 2.3.3 and their site suggest that android 4 will be supported in around month time.

It has 512 mb ram, Cortext A8 1GHz cpu and 8 gb internal storage with up to 32 gb SD card support.  Its wifi only model and support TV out using HDMI , mini usb and front camera for video call. If you want a full specifiction its here.

Its multitouch device and display quality is good. Thought its supported resolution is 480x800 only. Its sound quality its good, sound is clear and loud enough and video from youtube and dailymotion played fine.

I tried HDMI out, but was not successful trying to see device screen on my TV, might be cable problem but i suspect its device problem.

Home key, back , search and other standard android key are not backlight supported , so using them at night is guess work.

Battery takes time to get fully charged but once charged enough, it keeps going for atlest two days for normal reading and browsing use and works around 4 hour if watching you tube video.

Now on software part, by default it comes with app called app installer which let you install android apk file, browser, Email client, ES file explorer , Gallary and music application.

It was kind of disappointment by not seeing android market place application, but I was expecting it as it kind of entry level device. I tried to install market place by apk but its says not supported and web version keep complaining that you dont have any device attched to your google account. So I cant install any application from official android market place.

But I was able to install amazon store and getjar store and was able to install app from those store.

I installed PDF reader and worked great. I tried to install skype app but it never worked and was not able to login, so can not try it. But Fring worked great and also supported video calling feature.  And other normal application like Angry bird, guitar hero, piano worked great. 

I also liked ES file explorer as it allows to browse device easily and also it allows network shared storage. Like I shared my computer's folder over network and I was able to connect that computer and download contect from that shared folder using ES file explorer.  It also allows to connect to Dropbox and FTP server easily. But I tried only network shared folder.

Overall, its good device for reading and browsing and serve well as development device. It has fairly supported standard feature of tablet at fair price.



Saturday, December 24, 2011

Creating custom list view and adaptor in Android

I recently got new toy for myself a imuz TX72 7" android tablet to satisfy my book reading hobby.

I will write a seperate post for tablet, but as I got this tablet, I thought to port my Audiobook reader app to Android so I can here my audiobook on this tablet as well.

As I started to port, First thing I need to learn is how to create view and specially list view. I required to create custom Listview so I can show thumnail and other audiobook details.

So to start, First you need to create is activity. I also wanted to put button on main activity so I did not derived my activity from ListActivity but derived it from Activity. For new people to android like me, Activity is something that we see on screen , a view.

My main activity goes like below.

    
public class AudiobookReaderActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
       setContentView(R.layout.main);
       
       ListView list = (ListView) findViewById(R.id.BookList);
       list.setAdapter( new BookListAdaptor(this));  
    }  
}

Now we have list view, but how invidiual list item looks is decided by item's xml file, which provide layout and views details to be drawn as item.

Following is my list item, with one image and two text view.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
       "http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    
    <ImageView
        android:id="@+id/AlbumArt"        
      android:layout_width="55dip"
  android:layout_height="55dip"/>
    
 <LinearLayout xmlns:android=
              "http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical" >    
 
  <TextView xmlns:android=
                "http://schemas.android.com/apk/res/android"
      android:id="@+id/BookName"     
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textStyle="bold" 
      android:padding="3dp"
      android:textColor="#FFFF00" 
      android:textSize="16sp" >
  </TextView>
  
  <TextView xmlns:android=
                      "http://schemas.android.com/apk/res/android"
      android:id="@+id/TrackName"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:padding="3dp" >
  </TextView>
  
 </LinearLayout>
</LinearLayout>

Now look is set for list view, now we need to provide data to list, by creating adaptor class. Adaptor class act as model and provide data to list view.

Following is my custom list adaptor class to support Book data structure. Here getView method is importat as it uses our xml file to create liste item and decide our list view's look.

import java.util.ArrayList;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.content.Context;

public class BookListAdaptor extends BaseAdapter {
 
 public BookListAdaptor( Context context) {
  mContext = context;
  
  //load book list from file or database
  mBookList = new ArrayList();

  mBookList.add(new AudioBook("Harry Potter"));
  mBookList.add(new AudioBook("The Hobbit"));
 }

 @Override
 public int getCount() { 
  return mBookList.size();
 }

 @Override
 public Object getItem(int position) {
  return mBookList.get(position);
 }

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {  
  
        if (convertView == null) {
   LayoutInflater layoutInflator = 
                             LayoutInflater.from(mContext);
   convertView = layoutInflator.
                             inflate(R.layout.list_item, null);
        }
     
        TextView bookName = (TextView) convertView.
                                      findViewById(R.id.BookName);
        TextView trackName = (TextView)convertView.
                                      findViewById(R.id.TrackName);
        ImageView imageView = (ImageView)convertView.
                                      findViewById(R.id.AlbumArt);
  
  
  AudioBook book = mBookList.get(position);
  bookName.setText(book.bookName());
  trackName.setText(book.bookName());
  imageView.setBackgroundResource(android.R.drawable.btn_plus);
  
  return convertView;
  
 }

    private Context mContext;
    private ArrayList mBookList;
}

Book class looks something like following.

package com.niku;

import java.util.ArrayList;


public class AudioBook {
 
    public AudioBook( String aBookName) {
 mBookName = aBookName;
    }
 
    public String bookName() 
    {
        return mBookName;
    }

    private String mBookName;
}  
That's all. Final list view will looks like followign snap. Thanks fo reading my blog.






Friday, December 23, 2011

Crazy Flight a classic helicopter game now available on N9 Harmattan

I created this game - Crazy Flight, when I was on vacation in india, to please my nephew, so he can play on my phone and I can work on my computer.

Game is created using QML and C++ and backend and works on N9/N950 Harmattan plaform. Well programing did not take much time but creating graphics and polishing it took a while and around a week time I was able to publish this game on Ovi store for N9.

Game is vary simple to play,  you have to touch on screen to make plane go up and release touch to go down and avoid obstacle which may come.

You can download this game from Ovi store here. It free game with Ads.
Mobile link is here.


Here are few snapshot from game. If you have any comments I am glad to have those.





Saturday, December 17, 2011

Handling bluetooth headphone event with QmKeys in Harmattan

Currently I am working on upgrade of Audiobook reader application. As part of upgrade I am planing to support bluthooth headset support. In this upgrade I am planning to support only play/pause event.

Harmattan has QmSystem Qt library that provide events for various system activity. I used QmKeys API from QmSystem to capture and handle bluetooth headset event.

This is first time I am using QmSystem Library so I thought to put whatever I learned in blogpost in hope that it might help someone.

Following is my code to capture bluetooth headset event. It can be used to capture other system key event as well like Powekey, Volume key, Camera , keyboard slider and others.

First add qmsystem2 to CONFIG Qt project file.
CONFIG += qmsystem2
And also you need to include qmkeys.h.
#include <qmkeys.h> 
. Then need to create instace of QmKeys and connect its keyEvent SIGNAL to our SLOT.
mQmkeys = new MeeGo::QmKeys(this);

connect(mQmkeys, SIGNAL(keyEvent(MeeGo::QmKeys::Key, MeeGo::QmKeys::State)),
       this, SLOT(keyEvent(MeeGo::QmKeys::Key, MeeGo::QmKeys::State)));
Now our slot keyEvent will get called when ever there is key event. I am instrested only in play/pause event so following code list only those event.
void HeadsetKeyListener::keyEvent(MeeGo::QmKeys::Key key, 
    MeeGo::QmKeys::State state) {

    if( state != MeeGo::QmKeys::KeyDown ) {
        return;
    }

    switch( key) {
    case MeeGo::QmKeys::Play:
        emit playPauseClicked();
        break;
    case MeeGo::QmKeys::Pause:
        emit playPauseClicked();
        break;
    }
}
Well this is it, its vary simple to use.

Friday, December 9, 2011

Using QDeclarativeImageProvider to load QPixmap to QML Image element

Recently for my mobile application, I required cache image from network and use that in QML application. Prior to caching, I was using WebView element to show image from network, but I needed to show that image multiple places, to avoid multiple network request I decided to prefetch network image and show that using Image element.

To make it work, I downloaded network image to QPixmap using QNetworkAccessManager and then used QDeclarativeImageProvider to provide cached QPixmap to Image element.

As per documentation "The QDeclarativeImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML."  I also used it as proxy image provider. When actual Image data is not available my image provider class will provide some dummy image and when actual data is available it will provide actual image data.

Following is my code for my custom image provider derived from QDeclarativeImageProvider.

In following code, by providing QDeclarativeImageProvider::Pixmap as ImageType, I am saying I will povide QPixmap as Image type and in this case requestPixmap API will be called by declarative engine to fetch image. You can also use QDeclarativeImageProvider::Image, to provide QImage to Image and in that case requestImage API will be called.

#include <QDeclarativeImageProvider>

class ImageProvider: public QDeclarativeImageProvider
{
public:
    ImageProvider(ImageManager* manager)
        : QDeclarativeImageProvider(QDeclarativeImageProvider::Pixmap),
          mManager(manager)
    {}

    QPixmap requestPixmap(const QString &id, QSize *size, 
        const QSize &requestedSize)
    {
        int width = 320;
        int height = 53;

        QPixmap result;

        if( mManager->imageData() == 0 ) {
     QPixmap pixmap(requestedSize.width() > 0?requestedSize.width():width,
             requestedSize.height() > 0 ?requestedSize.height():height);

            pixmap.fill(QColor(id).rgba());

            if ( size ) *size = QSize(width, height);
            result = pixmap;
        } else {

            result = *mManager->imageData();
            if ( size ) *size =result.size();

            if (requestedSize.isValid()) {              
                result = result.scaled(requestedSize,Qt::IgnoreAspectRatio);
            } 
        }
        return result;
    }

private:
    ImageManager* mManager;
};
Now custom image provider is ready, but we need to register our image provide to declarative engine, so that it will now forward image loading request to our image provider. To do that, we need to use QDeclarativeEngine::addImageProvider API, as described in following code. Here in addImageProvider API, "MyImage" is provider name, that will be used in QML to indicate that our custom image provider should be used.
QScopedPointer view(new QDeclarativeView());
view->engine()->addImageProvider(QLatin1String("MyImage"), 
    new ImageProvider(ImageManager::instance()));
Now we are ready to use our custom image provider with Image element, like shown below. Here in Image.source we providing path as image://MyImage, which will tell system to use MyImage image provider and remaining part of url will be used as id in requestPixmap or requestImage parameter. Which can be used to decide what kind of image data to provide.
import QtQuick 1.0

Rectangle {
    id:container
    width: 320;height: 53
    anchors.horizontalCenter: parent.horizontalCenter    

    Connections{
        target: ImageManager
        onImageAvailable:{
            myImage.source = "image://MyImage/test"
        }
    }

    Image {
        id: myImage
        anchors.centerIn: parent
        source: "image://MyImage/"+container.color
    }
}
This is all that is needs to be done to implement custom image provide. Hope it will be usefull.