Friday, March 26, 2010

Android join tables

In my application, I have many tables and for a reason, I had to do a query using "join".
I'll not explain how to access a database, but just so you know, check on Google for
object SQLiteDatabase.

So I was checking at the method query , here is the information:

public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

Parameters
table :The table name to compile the query against.

For example:

Cursor cursor = myDataBase.query(
"myTableA" ,
new String[] { "_id", "name"},
null,null, null, null, null);

That's nice, but what if I want to a "join" ? I need more than 1 table in my query.
Well, at beginning I found CursorJoiner. Nice, I can join 2 cursors. But what if I have 3 or more joins to do ??

In fact, the parameter "table " (function query) can contains many tables (not just one).
For example:

Cursor cursor = myDataBase.query(
"myTableA a, myTableB b",
new String[] { "a._id", "a.name", "b._id", "b.name"},
"a.foreignKey = b._id",
null, null, null, null);


That was not difficult, but the definition of the parameter "table " was not so good.

Another solution would be to use SQLiteQueryBuilder.


SQLiteQueryBuilder myQuery = new SQLiteQueryBuilder();
myQuery.setTables("myTableA, myTableB");
myQuery.appendWhere("a.FK = b._id");
Cursor cursor = myQuery.query(myDataBase, null, null, null, null, null, null);

Tuesday, March 16, 2010

Android: add xml layout dynamically

For the application I'm creating, the user can use "search" function. This function will return a list of castles.
Here is the XML to display one result (/res/layout/element_result.xml). There is 1 button, 2 text fields and 1 image :


android:id="@+id/layoutElement"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
android:id="@+id/btnGo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/go"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
>

android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/presentation"
android:layout_alignLeft="@+id/presentation"
>

android:id="@+id/presentation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/image"
>

android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
>




Then, I created a XML layout (/res/layout/results.xml) who will contain the list of results. That means, there will be many times element_result.xml inside results.xml. There is a scrollView and a table layout.


android:id="@+id/widget28"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
android:id="@+id/scrollResult"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:layout_above="@+id/btnBack"
android:layout_alignParentLeft="true"
>
android:id="@+id/myTableLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>



android:id="@+id/btnBack"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/back"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
>




Ok, our views are ready. Now how to use them in Java. I read this blog, and that helps me a lot : Android LayoutWidth being disregarded by cascaded use of LayoutInflater.

Here is my activity file:

public class ResultActivity extends Activity{

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// "results" is for the xml file "results.xml"
setContentView(R.layout.results);

addElementResult();
}

public void addElementResult() {
// "myTableLayout" is the id of the element in results.xml
TableLayout tl = (TableLayout)findViewById(R.id.myTableLayout);
// we will use service from inflater
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);

//doing a loop to add many times the same xml
for(int i = 0; i < 17; i++) {
// "element_result" is the name of the xml file "element_result.xml".
// Create the itemView who will be added.
// itemView = element_result.xml
View itemView = inflater.inflate(R.layout.element_result, null);
// get the textView, and set the text to something
TextView t1 = (TextView) itemView.findViewById(R.id.presentation);
t1.setText("something" + i);

TextView t2 = (TextView) itemView.findViewById(R.id.description);
t2.setText("oh oh oh" + i);

//add the itemView
tl.addView(itemView, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
}
}


So the result will look like that :


Note: in results.xml, I created a scrollView because if there is 20 results, the user should be able to scroll down to see all the results.
Note: I used "tableLayout" to be able to add results one under another one.

Wednesday, March 10, 2010

Android: main.out.xml error


So it's been long time, I'm not doing Ruby anymore.
Now, for myself, I decided to create an Android application. At first, I wanted to create an Iphone application, but only people having a Mac can use the SDK... So let's use the Android SDK!
After doing the tutorial Hello World (see here), I started doing my application. And after a few minutes I had an error...

[2010-03-09 11:32:04 - shiro]Error in an XML file: aborting build.
[2010-03-09 11:32:05 - shiro]res\layout\main.xml:0: error: Resource entry main is already defined.
[2010-03-09 11:32:05 - shiro]res\layout\main.out.xml:0: Originally defined here.
[2010-03-09 11:32:05 - shiro]D:\workspace\shiro\res\layout\main.out.xml:1: error: Error parsing XML: no element found

For information, I'm using Eclipse. Why when I click on "run" I have this error ? Why Eclipse is creating a new file "main.out.xml" and then complain about it ? My application is really small, I didn't write any line of code in my main activity...

Well the error is simple, and it's not related to the application directly. It's a problem with Eclipse. To run the application, I must select the project (root folder) in the left column and then I can click on "run".

I had this error, because I was running the "main.xml". So Eclipse could not do anything with that.
Here is a noobie error, but it was difficult to find the solution...
I guess the next post will also concern Android application. It's always fun to discover new things :)