Showing posts with label Development. Show all posts
Showing posts with label Development. Show all posts

Android App Development: Implementing Search activities

Most Android phones have a search button. this button is used to search contacts,applications or anything on the phone. We can make use of the search functionality in our apps.

In this post we’re going to see how to implement search functionality to search for entries stored in a databaseand display them in a ListView.

our database has two tables: Countries and Names:

public class DBHelper extends SQLiteOpenHelper {public DBHelper(Context context) {super(context, "DemoDB", null, 1);}@Overridepublic void onCreate(SQLiteDatabase db) {StringBuilder builder=new StringBuilder();// countries tablebuilder.append("CREATE TABLE Countries ");builder.append("(_id INTEGER PRIMARY KEY AUTOINCREMENT,");builder.append("NAME TEXT) ");db.execSQL(builder.toString());// Names table// Virtual table for full text searchbuilder.setLength(0);builder.append("CREATE VIRTUAL TABLE NAMES USING FTS3");builder.append("(");builder.append("name TEXT) ");db.execSQL(builder.toString());builder=new StringBuilder();//dummy dataInsertData(db);} void InsertData(SQLiteDatabase db) { ContentValues cv=new ContentValues();cv.put("NAME","USA");db.insert("Countries", "NAME", cv);cv.put("NAME","UK");db.insert("Countries", "NAME", cv);cv.put("NAME","Spain");db.insert("Countries", "NAME", cv);cv.put("NAME","ITALY");db.insert("Countries", "NAME", cv);cv.put("NAME","Germany");db.insert("Countries", "NAME", cv); cv=new ContentValues();cv.put("name","John");db.insert("NAMES", "name", cv);cv.put("name","Jack");db.insert("NAMES", "name", cv);cv.put("name","Ann");db.insert("NAMES", "name", cv);cv.put("name","Adam");db.insert("NAMES", "name", cv);cv.put("name","Sarah");db.insert("NAMES", "name", cv); }@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// TODO Auto-generated method stub}}

notice that the Names table is a VIRTUAL table. we created it as virtual to make use of Full Text Search (FTS3) feature in SQLite. this feature makes queries faster than that in regular tables.

then we add two functions to retrieve all rows from both tables:

/** * Return all countries * @return */public ArrayListgetCountries(){ArrayList countries=new ArrayList();SQLiteDatabase db=this.getReadableDatabase();Cursor c=db.rawQuery("select * from Countries", null);while(c.moveToNext()){String country=c.getString(1);countries.add(country);}c.close();return countries;}/** * Return all names * @return */public ArrayListgetNames(){ArrayList names=new ArrayList();Cursor c=this.getReadableDatabase().rawQuery("select * FROM Names", null);while(c.moveToNext()){String name=c.getString(0);names.add(name);}c.close();return names;}

and another two functions to retrieve data based on a search string:

/** * Return all countries based on a search string * @return */public ArrayListgetCountriesSearch(String query){ArrayList countries=new ArrayList();SQLiteDatabase db=this.getReadableDatabase();Cursor c=db.rawQuery("select * from Countries where NAME LIKE '%"+query+"%'", null);while(c.moveToNext()){String country=c.getString(1);countries.add(country);}c.close();return countries;}/** * Return all names based on a search string * we use the MATCH keyword to make use of the full text search * @return */public ArrayListgetNamesSearch(String query){ArrayList names=new ArrayList();Cursor c=this.getReadableDatabase().rawQuery("select * FROM Names WHERE name MATCH '"+query+"'", null);while(c.moveToNext()){String name=c.getString(0);names.add(name);}c.close();return names;}

then we will create our activity that has a list view like this:


we load data from database like this:

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); list=(ListView)findViewById(R.id.list); DBHelper helper=new DBHelper(this); ArrayList items=helper.getNames(); ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1,items); list.setAdapter(adapter);}

In order to handle the search dialog ourselves we need to create a xml file with search configurations such as the search dialog title, voice search capabilities, content provider for auto complete and so on. we create a file with the name searchable.xml in res/xmldirectory:

the android:hint attribute denotes a string that acts as a water mark on the search text box.
then we need to add an Intent Filter in out app’s AndroidManifest.xml file to our activity to handle the search dialog:

when you press the search button, type some text and click on search the activit’s onSearchRequested() function is called, then an Intent with the action Intent.ACTION_SEARCH is created and you activity is re-created with this intent.
the search intent has you search string as a string extra with the name SearchManager.QUERY. also it can carry a bundle of other extras with the name SearchManager.APP_DATA.

not all Android devices have a search button, so we can start the search dialog manually by calling the activity’s onSearchRequested() from a button or a menu item:

@Override public boolean onCreateOptionsMenu(Menu menu) { menu.add("Search").setOnMenuItemClickListener(new OnMenuItemClickListener() {@Overridepublic boolean onMenuItemClick(MenuItem item) { //launch the search dialogonSearchRequested();return true;}}); return true; }

we can pass some extra data as a bundle with our search dialog or an initial search string by overriding the activity’s onSearchRequested():

@Override public boolean onSearchRequested() { Bundle bundle=new Bundle();bundle.putString("extra", "exttra info");// search initial querystartSearch("Country", false, bundle, false);return true; }

we said before that the search query is passed as a String extra when our activity is re-created. so we can handle the searcgh string in our onCreate() like this:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); list=(ListView)findViewById(R.id.list); DBHelper helper=new DBHelper(this); Intent intent=getIntent(); // if the activity is created from search if(intent.getAction().equals(Intent.ACTION_SEARCH)){ // get search query String query=intent.getStringExtra(SearchManager.QUERY); ArrayList items=helper.getNamesSearch(query); //get extras, just for demonstration Bundle bundle=intent.getBundleExtra(SearchManager.APP_DATA); String info=bundle.getString("extra"); Log.v("extra", info); //bind the list ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1,items); list.setAdapter(adapter); } //activity created normally else{ ArrayList items=helper.getNames(); ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1,items); list.setAdapter(adapter); } helper.close(); }

we just extract the search string and any other extras and perform our search logic based on the search string.
and that’s was all about implementing search, stay tuned for another Android tutorial

More aboutAndroid App Development: Implementing Search activities

Android App Development: Implementing remote Android Services with AIDL

In the last post we saw how to use Android services to do time consuming operations in the background. in this post we will see how can a client application call the methods of a service defined in another application. this is achieved through Android Interface Definition Language (AIDL).

AIDL is a java like language that enables you to define an interface that both the application defining the service and the client application implement it.

the interface defines the functions that are needed to be called in the client application.

AIDL syntax is similar to that of Java, we can use the following data types in AIDL:

primitive data types: int, long, char, boolean,….String.CharSequence.List (ArrayList,Vector,…).the AIDL file is defined as follows:
open a notepad file and paste the following code in it: package com.mina.servicedemo;// service interfaceinterface IRemoteService { //sample method String sayHello(String message);}

take care of the package name com.mina.servicedemo.
we defined a methods sayHello(String message) that returns a string.

save the file with the name IRemoteService and change it’s extension to .aidl.copy the file to the src folder of your project.once you save and build the file, Android generates an interface java file with the name IRemoteService.java in the gen folder if the project.

now we want our service to expose this interface to client applications, so we return an implementation of the service in the onBind() method of our service:

package com.mina.servicedemo;import com.mina.servicedemo.IRemoteService.Stub;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.widget.Toast;public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {return mBinder;}// implementation of the aidl interfaceprivate final IRemoteService.Stub mBinder=new Stub() {@Overridepublic String sayHello(String message) throws RemoteException {return "Hello "+message;}};}}

the last thing to do in the service is to make its exported attribute in the AndroidManifest.xml file set to true like this:

our app structure can be like this:

now to our client application where we want to invoke methods from our service. the client application is a separate application with a different package name than that where the service is defined.

the client application needs a reference to the AIDL interface defined in the original applcation, this is done through the following steps:

in the client applicatio create a package with the same package name of that the service is defined in: com.mina.servicedemo.copy the AIDL file in this package.save and build and a new file called IRemoteService.java is generated. your app structure should be like this:

and we invoke the servcice methods in our activity like this:

package com.mina.serviceclient;import com.mina.servicedemo.IRemoteService;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MainActivity extends Activity {IRemoteService mRemoteService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent serviceIntent=new Intent(); serviceIntent.setClassName("com.mina.servicedemo", "com.mina.servicedemo.DemoService"); boolean ok=bindService(serviceIntent, mServiceConnection,Context.BIND_AUTO_CREATE); Log.v("ok", String.valueOf(ok)); } private ServiceConnection mServiceConnection=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// get instance of the aidl bindermRemoteService = IRemoteService.Stub.asInterface(service);try {String message=mRemoteService.sayHello("Mina");Log.v("message", message);} catch (RemoteException e) {Log.e("RemoteException", e.toString());}}};}

and that’s was all about calling remote services with AIDL, stay tuned for another Android tutorial

More aboutAndroid App Development: Implementing remote Android Services with AIDL

Have your App Development funded by the Crowd – or invest in an App yourself

There may be a thousand great ideas in your mind that you would like to convert into an app – you’ll find it difficult to keep your spirit up after realizing that the development will cost a lot more money than you are able to bring in.

So what to do?

Reaching out for investors and trying to persuade them of your app idea? You could do that, but I assume you actually would rather prefer to concentrate on the product instead of running after the money. Wouldn’t it be more convenient to show your idea to the crowd and let literally anyone who likes your app concept put little and medium amounts of money in it? That’s what appbackr, the wholesale marketplace for app developers, has been made for.

The crowd wants to be part of it

The idea of crowdfunding in general hasn’t been invented by appbackr, of course – rather does every share market function on the concept of many people acquiring portions of something by their investments. However crowdfunding hasn’t been very common so far when it comes to more every day things which haven’t to do with the business world in a narrower sense. That’s what Kickstarter’s mission was when it was founded in 2009: offering people a place where they could raise funds from the crowd for any of their products in the fields of art, design, games, music and writing.

Apps need backrs

While Kickstarter covers a wide range of topics, appbackr is completely focusing on the mobile app market. Here’s how it works for you…

… being a developer:

Submit your app concept to appbackr, providing them with some basic information like screenshots / mock-ups and what the app will be about.Above that you’ll have to define how much money has to be raised at least to fund the app development. It’s done within minutes.As soon the submittal has been approved by appbackr, it goes live in appbackr’s marketplace section.From now on any person who likes the idea of your app can buy a convenient number of copies at a wholesale price (persons who do this are called “backrs” what explains appbackr’s company name).Depending on the amount of wholesale copies they’ve purchased backrs get the revenue of the corresponding amount of sales when the app is published and sells.As soon as all backrs have got their return according to their number of wholesale copies purchased, all sales taking place afterwards are completely yours – until the end of time.

… being anyone who likes apps and wants to participate in their success:LSATmax at appbackr

Visit the appbackr marketplace to look for apps that are worth being funded.On the app detail pages you’ll find all relevant questions answered: How much funding does this app need? What’s the minimum amount of money I have to spend? Who else is backing that app? And, probably most important: What will be my return on investment?If you find the app worth being funded, you just buy your wholesale copies by PayPal. As long as the app’s reserve goal hasn’t been achieved, you won’t be charged.You’ll receive your return when the app goes live and sells. Backrs are either in a queue one after another (based on which one purchased copies first, second, etc.), or they get paid simultaneously based on the percentage of their copies.

Well, that’s pretty much it! Got curious? We appreciate your thoughts on appbackr – just leave your comment here, visit us on appbackr.com, follow us on @appbackr oder like us on Facebook!

Torsten Weindl markets appbackr, a wholesale marketplace for app developers as well as for anyone who likes to fund an app and participate in its success. Before appbackr Torsten’s been running his own affiliate business in Germany since 2003 and worked as an Online Sales & Content Manager for Amazon.de.

More aboutHave your App Development funded by the Crowd – or invest in an App yourself

Android App Development: Android Services

Android Service is used for long-running processes that do not require user interaction, such as calling a web service and parsing response. Or processes that need to be running even if the application that started the service is not on the foreground such as playing mp3 files in a music player.

we need to distinguish between A Service and a Thread or an AsyncTask: Threads or Async task perform their tasks in a background thread thus they do not block the main thread, while a service performs it’s work in the main thread. so if a service is performing an intensive task such as calling a web service, it may block the main thread until it finishes. So for intensive tasks a service should run it’s work in a background thread.

A service runs in the same process of the application and keeps running until stopped by itself, stopped by the user or killed by the system if it needs memory.

to create a service we create a class that extends android.app.Service and it would be like this:

public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}}

next we need to define our service in our AndroidManifest.xml file:

The service life cycle has the following events

onCreate(): called when the service is created.onStart(): Called when the service starts by a call to startService(Intent intent).onDestroy(): Called as the service is terminates.

A service can be called from an activity in two ways:

By calling startService(Intent intent).By binding to the service through an Binder object.

to start a service from an activity using this method, we create an intent and start the service like this:

Intent intent=new Intent(this,DemoService.class);startService(intent);

the startService(intent) method causes the onStart() method of the service to be called, so the service can execute it’s work like this:

public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();}public void doSomething(){// do some work}}

the service will keep running until it stops itself via stop stopSelf() after finishing work:

@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();stopSelf();}

or it can be stopped from the activity via stopService(Intent intent).

As the service runs in the same process of the application the service has only one instance (singleton) instance running. you may want to keep reference to this instance to perform periodical tasks or to call the service methods themselves.

to make the service bind-able we extends Binder class and return an instance of it in the service’s onBind(Intent intent) method:

public class DemoService extends Service {private final IBinder binder = new LocalBinder();@Overridepublic IBinder onBind(Intent arg0) {return binder;}public class LocalBinder extends Binder {DemoService getService() { return DemoService.this; } }@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();stopSelf();}public void doSomething(){// do something}}

then we bind the service from our activity by first creating a ServiceConnection object to handle the service connection/disconnection then binding to the service by an intent like this:

public class MainActivity extends Activity {DemoService mService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } ServiceConnection serviceConn=new ServiceConnection() { /** * service unbound, release from memory **/@Overridepublic void onServiceDisconnected(ComponentName name) {mService=null;} /** * service is bound, start it's work **/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService=((LocalBinder)service).getService();mService.doSomething();}}; @Override protected void onResume() { super.onResume(); // bind to the service by an intent Intent intent=new Intent(this,DemoService.class); // AUTO CREATE: creates the service and gives it an importance so that it won't be killed // unless any process bound to it (our activity in this case) is killed to bindService(intent, serviceConn, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); / unbind the service whena ctivity is destroyed unbindService(serviceConn); }}

notice that we unbind the service in the activity’s onDestroy() method to disconnect from the service and stop it from executing any further

and that’s was all about Android services, stay tuned for another Android tutorial.

More aboutAndroid App Development: Android Services

Android App Development: Parsing Web Service Response part 1

In a previous last post we saw how to call REST and SOAP web services. The web service reponse can be one of the following:

XML.SOAP.JSON.

Android offers three types of XML parsers:

DOM Parser.Pull Parser.SAX Parser.

we’ll demonstrate each using the following xml example:

Jack smith 28

which we need to parse to create an object from Person class:

public class Person{ public String firstName; public String lastName; public int age; }

Android provides org.w3c.dom library that contains classes used to parse xml by constructing a document and
matching each node to parse the info.
to parse our example response with DOM parser, we implement a function like this

void parseByDOM(String response) throws ParserConfigurationException, SAXException, IOException{ Person person=new Person(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new InputSource(new StringReader(response))); // normalize the document doc.getDocumentElement().normalize(); // get the root node NodeList nodeList = doc.getElementsByTagName("person"); Node node=nodeList.item(0); // the node has three child nodes for (int i = 0; i < node.getChildNodes().getLength(); i++) { Node temp=node.getChildNodes().item(i); if(temp.getNodeName().equalsIgnoreCase("firstname")){ person.firstName=temp.getTextContent(); } else if(temp.getNodeName().equalsIgnoreCase("lastname")){ person.lastName=temp.getTextContent(); } else if(temp.getNodeName().equalsIgnoreCase("age")){ person.age=Integer.parseInt(temp.getTextContent()); } } Log.e("person", person.firstName+ " "+person.lastName+" "+String.valueOf(person.age)); }

The previous method is good, it retrieves the info correctly, but it requires that you are familiar with the xml structure so that you know the order of each xml node.
luckily Android provides a better approach of parsing using SAX parser.

Android provides org.xml.sax package that has that provides the event-driven SAX parser.
to parse the previous response with SAX parser, we have to create a class extending DefaultHandler and override the following methods:

startDocument(): invoked when the xml document is open, there we can initialize any member variables.startElement(String uri, String localName, String qName, Attributes attributes): invoked when the parser encounters a xml node, here we can initialize specific instances of our person object.endElement(String uri, String localName, String Name): invoked when the parser reaches the closing of a xml tag. here the element value would have been completely read.characters(char[] ch, int start, int length): this method is called when the parser reads characters of a node value.

so our parsing class will be like this:

/* * SAX parser to parse persons response */public class PersonParser extends DefaultHandler{// arraylist to store person objectsArrayList persons;// temporary person objectPerson tempPerson;// string builder acts as a bufferStringBuilder builder;/** * Initialize the arraylist * @throws SAXException */@Overridepublic void startDocument() throws SAXException {pesons=new ArrayList();}/** * Initialize the temp person object which will hold the parsed info * and the string builder that will store the read characters * @param uri * @param localName * @param qName * @param attributes * @throws SAXException */@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {if(localName.equalsIgnoreCase.equals("person")){tempPerson=new Person();builder=new StringBuilder();}}/** * Finished reading the person tag, add it to arraylist * @param uri * @param localName * @param qName * @throws SAXException */@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// finished reading a person, add it to the arraylistif(localName.toLowerCase().equals("person")){this.persons.add(tempPerson);}// finished reading "firstname" tag assign it to the temp personelse if(localName.toLowerCase().equals("firstname")){tempPerson.firstName=builder.toString();}// finished reading "lastname" tag assign it to the temp personelse if(localName.toLowerCase().equals("lastname")){tempPerson.lastName=builder.toString();}// finished reading "age" tag assign it to the temp personelse if(localName.toLowerCase().equals("age")){tempPerson.age=Integer.parseInt(builder.toString());}}/** * Read the value of each tag * @param ch * @param start * @param length * @throws SAXException */@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// read the characters and append them to the bufferString tempString=new String(ch, start, length); builder.append(tempString);}}

the code is pretty easy, the parser iterates over each node, you check the current node name and take an action.

then we call the parser like this:

public ArrayList getPersons(final String response) throws ParserConfigurationException, SAXException, IOException{BufferedReader br=new BufferedReader(new StringReader(response));InputSource is=new InputSource(br);PersonParser parser=new PersonParser();SAXParserFactory factory=SAXParserFactory.newInstance(); SAXParser sp=factory.newSAXParser(); XMLReader reader=sp.getXMLReader(); reader.setContentHandler(parser); reader.parse(is); ArrayList persons=parser.persons;return persons;}

what if our repspone was JSON instead of xml. it would be something like this:

"persons"[{"person"{"firstName": "John", "lastName": "Smith", "age": 25}}{"person"{"firstName": "Catherine", "lastName": "Jones", "age": 35}}]

this response is a JSON Array with the name “persons”, this array consists of “person” JSON Objects.
to parse such a reponse:

public ArrayList getMessage(String response){JSONObject jsonResponse;ArrayList arrPersons=new ArrayList;try {// obtain the reponsejsonResponse = new JSONObject(response);// get the arrayJSONArray persons=jsonResponse.optJSONArray("persons");// iterate over the array and retrieve single person instancesfor(int i=0;imuch easier than the previous methods.
notice that we used the methods optJSONArray,optString,optInt instead of using getString,getInt because the opt methods return empty strings or zero integers if no elements are found. while the get methods throw an exception if the element is not found.

and that was all about parsing web service reponses, stay tuned next week for another tutorial

More aboutAndroid App Development: Parsing Web Service Response part 1