Sunday 31 July 2011

Using Java script in Android WebView through JSInterface

This is a very powerful way to implement java script into Android web view component using JavascriptInterface. You can easily invoke an android method from a WebView.

Let say :

There is a WebView ....
WebView web = new WebView();

Now we need to make it js enabled ...
WebSettings settings = web.getSettings();
settings.setJavaScriptEnabled(true);

Now , need to point it to our custom JSInterface class ..
web.addJavascriptInterface(new JSInterface(), "jsinterface");

Now, load a custom html to load ...

String html = new String();
html = ("<html><center><img border=\"0\" onClick=\"window.jsinterface.specialClick('" + parameter_1 + "','" + parameter_2 + "');\" " + " width='60dip' src=\"" + mediaSource + "\"></html>");
web.loadData(html, "text/html", "utf-8");

This html will load a image fetching from either a url or file ( mediaSource ) and we want to track the onClick method of WebView in the Android code itself. So, there is a method in the JSInterface called specialClick() which will do it. And to invoke the method into HTML code , use the code ..

onClick="window.jsinterface.specialClick('" + parameter_1 + "','" + parameter_2 + "');

Now, the time to write the JSInterface class and specialClick() method.

Create a class named JSInterface and put the code ...


public class JSInterface
{
public void specialClick(String param1, String param2)
{
Log.d("CZ","param1..." + param1 + " , param2..." + param2);
handler.post(new Runnable()
{
public void run()
{
}
});
}
}


In such way , whatever parameters you have passed from HTML onClick method , you will get it in Android code. So, connection between WebView javascript and Android native code is done.

For, further clarification and doubts , you may contact me ....  surojit.pakira@collectivezen.com




Thursday 7 July 2011

Android Simple Accordion or Collapse Panel

After a wise looking on internet I accept that fact , creating an Accordion component  in android which can be easily comparable with HTML/Java Script counterpart is never an easy task.
So, I have tried to develop such a component which may fulfill your requirement. This may not be the best way but one of the ways , for sure.

Here are couple of screen shots of the example :


First create a layout xml and give it the name "accordian.xml". Put the bellow code in it :

<?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:background="#ffffff"
android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Location" android:id="@+id/text1" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel1" android:visibility="gone"  android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Symptons" android:id="@+id/text2" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel2" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Location" android:id="@+id/text3" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel3" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Character" android:id="@+id/text4" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel4" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Factors" android:id="@+id/text5" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel5" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
<ListView android:id="@android:id/list" android:layout_width="fill_parent" android:visibility="gone"
android:layout_height="340dip"  android:drawSelectorOnTop="false"  android:dividerHeight="0px"/>
</LinearLayout>


Create java file and name it "AccordianSampleActivity.java" and put the bellow code in it :


import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;

public class AccordianSampleActivity extends ListActivity implements OnClickListener
{
public OnLongClickListener longClickListner;
LinearLayout panel1,panel2,panel3,panel4,panel5;
TextView text1,text2,text3,text4,text5;
View openLayout;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.accordian);

panel1 = (LinearLayout) findViewById(R.id.panel1);
panel2 = (LinearLayout) findViewById(R.id.panel2);
panel3 = (LinearLayout) findViewById(R.id.panel3);
panel4 = (LinearLayout) findViewById(R.id.panel4);
panel5 = (LinearLayout) findViewById(R.id.panel5);

//panel1.setVisibility(View.VISIBLE);

//panel1.setVisibility(View.VISIBLE);

//Log.v("CZ","height at first ..." + panel1.getMeasuredHeight());

text1 = (TextView) findViewById(R.id.text1);
text2 = (TextView) findViewById(R.id.text2);
text3 = (TextView) findViewById(R.id.text3);
text4 = (TextView) findViewById(R.id.text4);
text5 = (TextView) findViewById(R.id.text5);

text1.setOnClickListener(this);
text2.setOnClickListener(this);
text3.setOnClickListener(this);
text4.setOnClickListener(this);
text5.setOnClickListener(this);

}
@Override
public void onClick(View v)
{
hideOthers(v);
}
private void hideThemAll()
{
if(openLayout == null) return;
if(openLayout == panel1)
panel1.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel1, true));
if(openLayout == panel2)
panel2.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel2, true));
if(openLayout == panel3)
panel3.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel3, true));
if(openLayout == panel4)
panel4.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel4, true));
if(openLayout == panel5)
panel5.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel5, true));
}
private void hideOthers(View layoutView)
{
{
int v;
if(layoutView.getId() == R.id.text1)
{
v = panel1.getVisibility();
if(v != View.VISIBLE)
{
panel1.setVisibility(View.VISIBLE);
Log.v("CZ","height..." + panel1.getHeight());
}

//panel1.setVisibility(View.GONE);
//Log.v("CZ","again height..." + panel1.getHeight());
hideThemAll();
if(v != View.VISIBLE)
{
panel1.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel1, true));
}
}
else if(layoutView.getId() == R.id.text2)
{
v = panel2.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel2.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel2, true));
}
}
else if(layoutView.getId() == R.id.text3)
{
v = panel3.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel3.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel3, true));
}
}
else if(layoutView.getId() == R.id.text4)
{
v = panel4.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel4.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel4, true));
}
}
else if(layoutView.getId() == R.id.text5)
{
v = panel5.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel5.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel5, true));
}
}
}
}

public class ScaleAnimToHide extends ScaleAnimation
{

       private View mView;

       private LayoutParams mLayoutParams;

       private int mMarginBottomFromY, mMarginBottomToY;

       private boolean mVanishAfter = false;

       public ScaleAnimToHide(float fromX, float toX, float fromY, float toY, int duration, View view,boolean vanishAfter)
       {
           super(fromX, toX, fromY, toY);
           setDuration(duration);
           openLayout = null;
           mView = view;
           mVanishAfter = vanishAfter;
           mLayoutParams = (LayoutParams) view.getLayoutParams();
           int height = mView.getHeight();
           mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin - height;
           mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) - height;
         
           Log.v("CZ","height..." + height + " , mMarginBottomFromY...." + mMarginBottomFromY  + " , mMarginBottomToY.." +mMarginBottomToY);
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t)
       {
           super.applyTransformation(interpolatedTime, t);
           if (interpolatedTime < 1.0f)
           {
               int newMarginBottom = mMarginBottomFromY + (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime);
               mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin,mLayoutParams.rightMargin, newMarginBottom);
               mView.getParent().requestLayout();
               //Log.v("CZ","newMarginBottom..." + newMarginBottom + " , mLayoutParams.topMargin..." + mLayoutParams.topMargin);
           }
           else if (mVanishAfter)
           {
               mView.setVisibility(View.GONE);
           }
       }
}
public class ScaleAnimToShow extends ScaleAnimation
{

       private View mView;

       private LayoutParams mLayoutParams;

       private int mMarginBottomFromY, mMarginBottomToY;

       private boolean mVanishAfter = false;

       public ScaleAnimToShow(float toX, float fromX, float toY, float fromY, int duration, View view,boolean vanishAfter)
       {
           super(fromX, toX, fromY, toY);
           openLayout = view;
           setDuration(duration);
           mView = view;
           mVanishAfter = vanishAfter;
           mLayoutParams = (LayoutParams) view.getLayoutParams();
           mView.setVisibility(View.VISIBLE);
           int height = mView.getHeight();
           //mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin + height;
           //mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) + height;
         
           mMarginBottomFromY = 0;
           mMarginBottomToY = height;
         
           Log.v("CZ",".................height..." + height + " , mMarginBottomFromY...." + mMarginBottomFromY  + " , mMarginBottomToY.." +mMarginBottomToY);
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t)
       {
           super.applyTransformation(interpolatedTime, t);
           if (interpolatedTime < 1.0f)
           {
               int newMarginBottom = (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime) - mMarginBottomToY;
               mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin,mLayoutParams.rightMargin, newMarginBottom);
               mView.getParent().requestLayout();
               //Log.v("CZ","newMarginBottom..." + newMarginBottom + " , mLayoutParams.topMargin..." + mLayoutParams.topMargin);
           }
       }

}
}


Before compilation , make sure you have made an entry in the manifest file for the new activity.

In this app , I have implemented the accordion panel what I just said..
https://market.android.com/details?id=com.lcs.mmp.lite

Wednesday 15 June 2011

Using Android with PureMVC and OrmLite

There are very limited examples or tutorial about how to integrate PureMVC as a framework in your android application in the web. You will also find some more examples about how should you incorporate ORMLite as a ORM system in your application.

But , if you want to use both in your application to make it more structured and concrete , well... then you are in trouble , cause there is no such example code or tutorial available so far in the internet.

After spending a lot of time in it , atlast I able to integrate all of them , which is Android-PureMVC-ORMLite successfully.

Please find the sample project where I have implemented Android , PureMVC as well as ORMLite.
I am assuming people whoever reading this post have clear knowledge in all of them (Android,PureMVC, ORMLite).

Please download the sample code from here.

If you are not then please refer to ,
http://developer.android.com/index.html for Android
http://puremvc.org/content/view/98/189/ for PueMVC
http://ormlite.com/sqlite_java_android_orm.shtml for OrmLit

Setup Sample App : Please download the app and import this as Android Project into your workspace.
There are some external jars which needs to be added to the Project's build path. So, please do that before compiling the project.

Goal of the Sample App : This a very simple app with 2-3 screens. People can login into system or sign up ( in case they don't have a user ) in it.
On successful signup/login , there will be a welcome screen shown.
That's it !!!

App flow : According to PureMVC , proxy should have all the data connection and database transaction. In this app, there is a single proxies which is MemberProxy (com.cz.sample.member.model..MemberProxy). So, we need to include the ORMLite in the proxy itself.
According to OrmLite , there should be a Database Helper in the app and so we have here in the app( com.cz.sample.db.DatabaseHelper), which holds all the db related information i.e. database name , table name etc.

So, to incorporate ORMLite into PureMVC , we have to create an instance of DBHelper in the MemberProxy and do the needful.
In the app we have only two methods which are doLogin() and doSignUp(). First one is to read the database and second one is to write. So, you will have a clear idea about both read and write.



You may email me in this a/c for further question and suggestion : surojit.pakira@collectivezen.com

Android-PureMvc-OrmLite


This app I have developed using both PureMVC and OrmLite :
https://market.android.com/details?id=com.lcs.mmp.lite