February 17, 2011
Android SQLite Library Example Code
I have just uploaded QCDBAccess. It is a SQLite wrapper for Android that is easy to use, thread-safe, and allows you to use transactions if you choose. It is the same code that has been available for QCAndroid hybrid application developers for a few years. I thought I would pull it out and give it its own life for those that want to use it on their own.
You can download it from SourceForge and find out more about it, including the API, at the QuickConnectFamily site.
As with all of the things I’m making available I have tried to make this as easy to use, highly functional, and small as possible.
The jar file is only 8k in size but the library doesn’t restrict your use of the databases in any way.
Here is a simple example of how to use the library to do a query against a SQLite database file included in your applications’ assets directory. Notice that I’m checking to see if the user has entered a name to query against in an EditText object from the user interface. If they have then I’m going to use a prepared statement. The EditText object in this example has been passed into the method in which this code exists.
String sql = “SELECT * FROM user”;
String[] statementParams = null;
EditText nameInput = (EditText)methodParameters.get(1);
String name = nameInput.getEditableText().toString().trim();
if(name.length() > 0){
sql += ” WHERE name = ?”;
statementParams = new String[1];
statementParams[0] = name;
}
try {
retVal = DataAccessObject.getData(theActivity, “demo.sqlite”, sql, statementParams);
} catch (DataAccessException e) {
e.printStackTrace();
}
The DataAccessResult variable retVal is going to be returned from this method later. This DataAccessResult is a Bean that contains resultant field names, the records returned from the query, and a database error description if and only if a database error happened.
the getData method is passed the Activity with which the database is associated with. This is usually the main Activity in an Android Application. The second parameter is the name of the SQLite database file to be used. The third parameter is SQLite SQL assembled either as a standard or prepared statement. The last parameter is an array of Objects that are to be bound to the ? characters if the SQL is a prepared statement or null if it is not a prepared statement.
Inserting data is done in very much the same fashion. Once again I have an EditText object in the UI from which I’m getting the name to be inserted into the table. I’m also generating a unique identifier just to make this a little more interesting. You could do an auto incremented id in your table if you want.
EditText nameInput = (EditText)parameters.get(1);
String nameToAdd = nameInput.getEditableText().toString().trim();
String[]statementParams = {UUID.randomUUID().toString(), nameToAdd};
DataAccessResult aResult = null;
try {
aResult = DataAccessObject.setData(theActivity, “demo.sqlite”,
“INSERT INTO user VALUES(?,?)”,
statementParams);
return aResult;
} catch (Exception e) {
e.printStackTrace();
}
Notice that once again I have chosen to use a prepared statement. I’m doing this to avoid SQL insertion attacks. It never hurts to avoid those.
If you are going to do several insertions you should use transactions to make sure you data stays clean. There is a startTransaction method and an endTransaction method in the DataAccessObject. Use those before and after multiple setData calls and you will be safe.
January 25, 2011
QCJSON Now Thread Safe
The changes described here are found in QCJSON v. 1.0.2 available on sourceForge . The license is BSD. You can get the source code from the git repository on sourceForge using the command:
git clone git://qcjson.git.sourceforge.net/gitroot/qcjson/qcjson
or look at it online.
I’ve been pondering how to make QCJSON thread safe meaning that you could read and write to the same stream from separate threads safely without impacting any other streams that may be being used in the same or other threads.
The problem description is that you don’t want to start a read when one is part way complete. Nor do you want to start a write in the middle of another write. Both of these situations plus mixing read and write can cause serious data corruption.
I briefly played with the idea of creating a Class that would contain a static semaphore. This static semaphore would control access to the reading and writing behavior of the existing code. The problem is that with this approach reading or writing to one stream on one thread would cause any other threads to wait at the semaphore claim location even if the stream that it wished to write to was in no way associated with the stream that was currently being used. In other words reading or writing on one stream would block reading and writing on all streams until it was complete. Obviously this is an unacceptable solution. You might as well just write in one thread.
Since there is no way of interrogating an input our output stream object in Java it isn’t possible to hide the threading locks from the programmer using the QCJSON library and allow independent streams to work in independent threads.
While I’ve thought through several options the one that seems the best is to allow you, the developer, to pair input and output streams and include a semaphore in this pairing. This is going to require a new class.
For lack of a better name I am calling this new class org.quickconnect.json.JSONStreamProtector. It has a default constructor that takes no parameters and has one public method, protectJSONStream(JSONStream aStream).
If you instantiate a JSONStreamProtector you can pass the protectJSONStream method any number of JSONInputStreams and JSONOutputStreams. Any streams that you pass as a parameter to this method will share the same semaphore. Thus when you call readObject or writeObject on the protected streams any threads that would be using these streams will block in their readObject or writeObject methods until it is safe to proceed.
Using JSONStreamProtector
Changes have been made in the JSONInputStream and JSONOutputStream classes so that if a protector has been set for them the stream will claim or wait until it is able to claim the semaphore in its defined protector.
You needn’t put the protector in a collection or some other class’ attributes in order for it to not be garbage collected. Passing one JSONStream to the protectJSONStream method is sufficient.
In Example 1 the code shows how to protect a single output stream from three separate threads trying to write to the stream simultaneously. Input streams work the same way. Protecting an input/output stream pair that work on the same underlying resource would just mean using the same protector for both streams.
Any stream can only have one protector at a time. This keeps your code from accidentally getting in a cross-locking situation. You can switch the protector is is using at any time by calling the new protectors’ protectJSONStream method.
Example 1:
try {
/*
* Add three output streams to the same file and then have each of them send
* json to the stream. Make sure that no data corruption occurs.
*/
JSONStreamProtector aProtector = new JSONStreamProtector();
FileOutputStream testOut = new FileOutputStream(aFile);
/*
* stuff to write to file
*/
int[] testIntArray = {7,10,0,-789};
String[] testStringArray = {"What","is","happening?"};
TestObject anObject = new TestObject("Hello there.", 7, new Date(1067899));
/*
* do the running
*/
JSONOutputStream jsonTestOut1 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut1);
Thread testThread1 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testIntArray));
JSONOutputStream jsonTestOut2 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut2);
Thread testThread2 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testStringArray));
JSONOutputStream jsonTestOut3 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut3);
Thread testThread3 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, anObject));
testThread1.start();
testThread2.start();
testThread3.start();
} catch (Exception e) {
e.printStackTrace();
}
The source code for the protector class is simple so I’ll just put it here.
package org.quickconnect.json;
import java.util.concurrent.Semaphore;
public class JSONStreamProtector{
public void protectJSONStream(JSONStream aJsonStream){
private Semaphore semaphore = new Semaphore(1, true);
aJsonStream.setProtector(this);
}
protected void claim() throws InterruptedException{
semaphore.acquire(1);
}
protected void free(){
semaphore.release(1);
}
}
January 21, 2011
Android and JSON
As I have been working with Android I found that the JSON library included in the standard Android library set was the one from JSON.org which is intended as a reference implementation. When using that implementation I found that it is much more confusing than it needs to be. To solve this problem I created a generic Java implementation usable in any Java situation including Android. You can get it from sourceForge. A JavaDoc API is included in the download.
Like the JavaScript implementation from JSON.org that is being embedded in all new browsers my implementation has stringify and parse methods. These methods behave just like the ones in JavaScript and are static methods of the JSONUtilities class.
The stringify method receives most any Serializable object, runs up its inheritance tree, and returns a JSON string that includes all of the attributes of all of the objects and all of the values from all of the collections found. The only Serializable objects not accepted are raw Java Objects, since they have no attributes, and anything that inherits from java.awt.container.
The JSONUtilities.parse method takes a JSON formatted string as its parameter and returns either a HashMap or an ArrayList. What is returned is dependent upon if the JSON container is an array or an associative array(object/map).
Here is an example from the JavaDocs of the string being parsed and what is produced.
- Example 1 JSON: [“1”, “hello”, {“name”:”fred”,”age”:”23″}]
- Example 1 Result: An ArrayList with three values: a String “1”, a String “hello”, and a HashMap as the third value in the ArrayList. This HashMap has two key/value pairs: “name”/”fred” and “age”/”23”.
- Example 2 JSON: {“state”:”Idaho”, “city”:”Rexburg”, “people”:[“bob”,”sue”]}
- Example 2 Result: A HashMap with three key/value pairs: “state”/”Idaho”, “city”/”Rexburg”, and “people”/ArrayList. The ArrayList that is the value for the “people” key has two String values “bob” and “sue”.
Object anObject = JSONUtilities.parse(aJSONString);
Here is an example of how the JSONUtilities stringify method works.
- Example 1 Object: An ArrayList with three values: a String “1”, a String “hello”, and a HashMap as the third value in the ArrayList. This HashMap has two key/value pairs: “name”/”fred” and “age”/”23”.
- Example 1 JSON result: [“1”, “hello”, {“name”:”fred”,”age”:”23″}]
- Example 2 Object: A HashMap with three key/value pairs: “state”/”Idaho”, “city”/”Rexburg”, and “people”/ArrayList. The ArrayList that is the value for the “people” key has two String values “bob” and “sue”.
- Example 2 JSON result: {“state”:”Idaho”, “city”:”Rexburg”, “people”:[“bob”,”sue”]}
String jsonString = JSONUtilities.stringify(anObject);
In addition to these two utility methods there are two stream wrapper classes. These behave much the ObjectOutput stream methods that are part of JavaSE. They allow you to JSON an object into a stream and parse an object out of a stream. These streams can be anything that inherits from InputStream or OutputStream. For example, these could be a FileInputStream, a FileOutputStream, an input or output stream from a socket, etc.
Here is a code sample where the JSONOutputStream is wrapped around a FileOutputStream. This would write the JSON to a file on disk.
HashMap aMap = new HashMap();
aMap.put(“stringOne”, “Some sort of string”);
aMap.put(“aNumber”, 16.5);
aMap.put(20,”some other stuff” );
aMap.put(“aTesterDate”,new Date());
try{
FileOutputStream aFileOutStream = new FileOutputStream(“testFile.txt”);
JSONOutputStream aJSONFileStream = new JSONOutputStream(aFileOutStream);
aJSONFileStream.writeObject(aMap);
}
catch(Exception e){
//do your exception handling
}
The code to read and parse JSON from a stream is similar. Here is an example reading from a file.
try {
FileInputStream aFileInputStream = new FileInputStream(“testFile.txt”);
JSONInputStream inFromFile = new JSONInputStream(aFileInputStream);
Object anObject = inFromFile.readObject();
//if anObject is expected to be an ArrayList cast it as such and use it.
//if anObject is expected to be a HashMap cast it as such and use it.
} catch (Exception e) {
//do your exception handling here
}
I hope this helps you with your data communications in Android, JavaSE, and Java Enterprise.
August 22, 2010
QuickConnectFamily 1.6.3 is now available
I am uploading to sourceForge the latest version of QuickConnect right now.
This new version of QC is a maintenance version and has two fixes in it.
The first is a fix to the display of iAdds. Previously the iAdd seemed to disappear but was still taking up screen space and masking the area it was covering.
The second fix regarded a crash when using native databases with null values in fields.
Both of these defects have been fixed.
March 26, 2010
Using HTML Links to Trigger Activity in Hybrid Applications
For those of you who are wanting to use <a> link tags to trigger behavior I have put together an example of how to make these work.
The main problem when you want to use a link rather than a button, div, image, or some other HTML element is to stop the standard behavior of loading the new page. This is readily accomplished using QuickConnect since the framework includes a method with the signature ‘stopDefault(event)’.
Any time you call this method the default behavior of any type of event whether it be load a page, scroll, etc. is not executed. The code behind this method is very strait forward as you can see here.
//stop an event from doing its’ default behavior
function stopDefault(event){
if(event){
event.preventDefault();
}
}
The fully working QuickConnect example code is seen below. This example will also be included in the next beta download and the first QC v1.6 release. This example is built off of the ViewSwapping example and includes an addition of how to interact with the in-app map QuickConnect behavior. Because of this the index.html file code is very similar to that seen in my previous post.
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd“>
<html>
<head>
<title>QCXcodeTemplate</title>
<base href=“mobile/”>
<meta http-equiv=“content-type” content=“text/html; charset=utf-8”>
<meta name=“viewport” content=“width=device-width, minimum-scale=1.0, maximum-scale=1.6”>
<meta name=“apple-mobile-web-app-capable” content=“YES”>
<link rel=“stylesheet” href=“main.css”>
<script type=“text/javascript” src=“Parts/parts.js” charset=“utf-8”></script>
<script type=“text/javascript” src=“../QCJSLib/setupQC.js” charset=“utf-8”></script>
<script type=“text/javascript” src=“main.js” charset=“utf-8”></script>
</head>
<body onload=“load();”>
<div id=‘view1’ class=‘view’>
<a href=“” onclick=‘showView(2)’ >Show View 2</a>
<p>Here is some text for display in View 1.</p>
</div>
<div id=‘view2’ class=‘view’ style=‘background-color:lightgreen;’>
<a href=“” onclick=‘showView(1)’ >Show View 1</a>
<p>Here is some text for display in View 2.</p>
</div>
<a href=“” onclick=‘triggerShowMap()’>Show Map</a>
</body>
</html>
The main difference shown here is that the buttons have been replaced by link (anchor) tags. Notice that the src attribute is set to an empty string. It can be set to anything but what ever it is set to is ignored because of a call to the stopDefault method described above.
Additionally I have included a link that activates the in-app map behavior. This new map activation link is the last element shown in the body tag.
Since the CSS hasn’t changed between this example and the previous one I will not provide it again. You can see it in my previous post.
The Javascript is very similar. As you can see here the only difference between the ShowView example code and the UsingLinksAsTriggers is the inclusion of a call to the stopDefault method.
function load()
{
showView(1);
}
var currentView = null;
function showView(viewNumber){
//stop the loading of the new page since this is triggered by a link
stopDefault(window.event);
var nextView = document.getElementById(‘view’+viewNumber);
//if there is a view to change to
if(nextView){
//if at least one view has been displayed
if(currentView){
currentView.style.zIndex = 0;
currentView.style.opacity = 0;
}
nextView.style.zIndex = 10;
nextView.style.opacity = 1.0
//reset currentView
currentView = nextView;
}
}
The method for showing a map inside your application, triggerShowMap, is much like the method in the ShowMap example. The difference is once again the addition of the call to stopDefault.
function triggerShowMap(event)
{
//stop the loading of the new page since this is triggered by a link
stopDefault(window.event);
//a location consists of a latitude, a longitude, and a description
var locationsArray = new Array();
var rexburg = new Array();
rexburg.push(43.82211);
rexburg.push(-111.76860);
rexburg.push(“County Court House”);
locationsArray.push(rexburg);
var wyoming = new Array();
wyoming.push(42.86);
wyoming.push(-109.45);
wyoming.push(“Wyoming Place”);
locationsArray.push(wyoming);
var wilderness = new Array();
wilderness.push(45.35);
wilderness.push(-115);
wilderness.push(“River of No Return Wilderness”);
locationsArray.push(wilderness);
var sandwichShop = new Array();
sandwichShop.push(42.86);
sandwichShop.push(-112.45);
sandwichShop.push(“Somewhere Sandwiches”);
locationsArray.push(sandwichShop);
/*
* possible map types are standard, satelite, hybrid
* The showMap method call is part of the QuickConnect Framework.
* It is not a standard call
*/
var showDeviceLocation = true;
showMap(locationsArray, showDeviceLocation, ‘standard’);
}
The examples shown here don’t use the QuickConnect mappings and stacks but the same call to stopDefault would need to be made if you were calling the standard ‘handleRequest’ method. I usually put the stopDefault call in the first control function executed for the given command.
Hopefully this clears up how to use a link within hybrid applications.
December 30, 2009
Apple Push now Available
The QuickConnectFamily framework now includes support for Apple push functionality. In addition to retrieving any update information for you and sending it to your JavaScript when your app starts if a push is received when your app is running your JavaScript is passed the notification.
Hopefully you can use it.
iPhone Enterprise Data Synchronization
The QuickConnectFamily framework now has Enterprise Data Synchronization built in. It is included in the 1.6 beta 9 and later versions. In beta 9 the only tested version is for the iPhone but in beta 10 there will be tested versions for the iPhone, Android, Blackberry, and Palm Web OS devices.
You can find a ‘how to’ on the wiki.
An example app, synchronization, is also include in the 1.6 beta 9 and later downloads. It uses http. You should use https in your implementation
It was fun to create this ability. I hope you can use it.
Lee
September 24, 2009
QuickConnectiPhone 1.6 Beta 1 is now available
QCiPhone 1.6 beta 1 is now available from the sourceForge repository. It includes access to the Contacts API via JavaScript as well as a new way of doing GPS locations and tracking. There are two new examples to show how to use the new functionality, GPSExample and Contacts Example.
The old in-application map functionality has been commented out in anticipation of Beta 2 which will include the access to the new 3.0 Map API and in-application email.
Push from within JavaScript and receiving pushes in JavaScript planned for Beta 3.
September 5, 2009
QuickConnectAndroid 1.5 RC_1 Available
QuickConnectAndroid 1.5 RC_1 is now available for download from sourceForge. It includes SQLite access with transactions, recording and playing recorded audio, playing system sounds, vibrating the device, and getting device information such as OS version, time zone, country, etc.
There are examples and source code for each of these capabilities. QCAndroid is now updated to use the same version of the JavaScript QuickConnect framework that QCiPhone 1.5.0 and QCMac 1.5.0 uses. Now all JavaScript should be portable between these platforms. The next upgrade will be QCLinux.
August 29, 2009
QuickConnectiPhone 1.5.0 is now available
QCiPhone 1.5.0 has just been uploaded to sourceForge. They are saying that it may take about 15 minutes to become visible as the default download for OS X machines.
A note to 3.0 API users. The dashcode QC template no longer appears as an option. I am looking for ways to get it to show up again.End
Because of the 3.0 Dashcode changes I have not been able to update the Dashcode examples to the latest QC source. All of the Xcode examples are updated.
The release includes examples of how to use the video and audio tags in booth QCiPhone and QCMac applications.
QuickConnectMac 1.0 is also included in this release. It allows you to create hybrid applications that run on Mac machines just like you do for the iPhone and iPod touch.
QuickConnectPHP 1.0 is another template that can be used on the Mac side. It isn’t used to create hybrid applications but is used to create PHP web applications.
Also included, for those interested, is QCErlang 1.0. It is an updated version of an Xcode template for developing erlang applications. It includes auto-completes for most of the commonly used functions.
Defect fixes in this release include:
1. UIWebView no longer ends up with a black background after re-displaying the Default.png file while the page loads.
2. DataAccessObject in-browser database use fixed and updated to new methodology for the retention of which BCF in the stack is to be called next.
3. Updated the embedded map code to use the current data passing scheme from and to Objective-C
4. HTML Elements with touch events inside of Elements made scrollable no longer react to ontouchstart, ontouchmove, and ontouchend unless the event is not due to scrolling