Loading Content Values from JSON - android

I'm trying to load Content Values into a database. The code here works:
private void processTable(final JsonReader tableReader, final ModelLoader loader) throws IOException
{
tableReader.beginArray();
while (tableReader.hasNext()) {
String id = loader.getIdColumnName();
final ContentValues cv = loader.parseModel(tableReader);
persistData(loader.getTableName(),id, cv);
}
tableReader.endArray();
}
However, when I add an additional part into it, it fails.
private void processTable(final JsonReader tableReader, final ModelLoader loader) throws IOException
{
tableReader.beginArray();
while (tableReader.hasNext()) {
String id = loader.getIdColumnName();
final ContentValues cv = loader.parseModel(tableReader);
if (loader.getModelType() == Filter.LOADER.getModelType()) //Checks to see if the filter sub arrays are there
{
while(tableReader.hasNext())
{
String name = "";
try{
tableReader.
name = tableReader.nextName();
} catch (Exception e) {
tableReader.skipValue();
continue;
}
if (name.equals("ImageOverlays"))
processTable(tableReader, mLoader.getSpecificLoader("ImageOverlays"));
else if (name.equals("ColorOverlays"))
processTable(tableReader, mLoader.getSpecificLoader("ColorOverlays"));
}
}
persistData(loader.getTableName(),id, cv);
}
tableReader.endArray();
}
The purpose of the additional code is to get a particular item from the Filters and then process them. When I use this code, I don't even get any values for the Filters which I used to before.
I think that me skipping the values is somehow screwing up the ContentValues cv that I declare before it.
Thanks for any help.

So Its your Interior loop causing the problem which is skipping the JSON Objects that have to be parsed...
And Yeah the Content Values as you mentioned in the comments are not valid by the time you reach the end of the loop.

Related

Returns zero for all values retrieved from the parse database

I'm using parse backend to store and retrieve the datas for my android app, the storing gets done properly but i have problem in retrieving it. I just went through the parse documentation to retrieve the result but what i get is just 0 for all the retrieved values..im suret that the class exists in the parse cloud with valid values but still i get 0 for all the queries.. this is my code to save:
Toast.makeText(getApplicationContext(),"writing to parse",Toast.LENGTH_SHORT).show();
ParseObject dataObject = new ParseObject("Score");
dataObject.put("correct",correctAnswers);
dataObject.put("wrong",wrongAnswers);
dataObject.put("percent", percentage);
dataObject.saveInBackground();
this is how i get back the saved data
ParseQuery<Score> query = ParseQuery.getQuery("Score");
try {
List<Score> scoreList = query.find();
} catch (ParseException e) {
e.printStackTrace();
}
query = ParseQuery.getQuery("Score");
final Activity ctx = this;
query.findInBackground( new FindCallback<Score>() {
#Override public void done(List<Score> scoreList, ParseException e) {
if ( e == null ) {
ParseObject dataObject = ParseObject.create("Score");
int p = dataObject.getInt("correct");
int q = dataObject.getInt("wrong");
int r = dataObject.getInt("percent");
Toast.makeText(ExamRecordActivity.this,String.valueOf(p),Toast.LENGTH_SHORT).show();
Toast.makeText(ExamRecordActivity.this,String.valueOf(q),Toast.LENGTH_SHORT).show();
Toast.makeText(ExamRecordActivity.this,String.valueOf(r),Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ctx,
"Error updating questions - please make sure you have internet connection",
Toast.LENGTH_LONG).show();
}
}
});
Inside the done method you are creating a new by calling ParseObject dataObject = ParseObject.create("Score"); and then trying to read values from it without putting any in.
I don't know what the structure of your class is but you need to be iterating through List<Score> scoreList in order to get the queried data.

How to get timestamp(rowversion) from sql azure to android with mobileservice

i have a problem getting timestamp(rowversion) from my SQL Azure database.
In my tables there is a column with datatype timestamp. This timestamp isn't similar to datetime, it's more like a rowversion.
I can get all other data in this table with the query from MobileServiceTable, there is no problem.
But this special datatype is a problem.
My class for this table looks like:
public class ArbeitsgangBezeichnung {
#com.google.gson.annotations.SerializedName("id")
private int ID;
#com.google.gson.annotations.SerializedName("ABZ_ArbeitsgangBezeichnungID")
private int ABZ_ArbeitsgangBezeichnungID;
#com.google.gson.annotations.SerializedName("ABZ_Bezeichnung")
private String ABZ_Bezeichnung;
#com.google.gson.annotations.SerializedName("ABZ_RowVersion")
private StringMap<Number> ABZ_RowVersion;
//constructor, getter, setter, etc....
}
If i login in Azure and look at the table, there are my example values and the automatic generated timestamp. The timestamp value looks like "AAAAAAAAB/M=". If i login in sql database and let me show the data, then for timestamp there is only "binarydata" (in pointed brackets) and not that value as it is shown in Azure.
The variable "ABZ_RowVersion" should include this timestamp, but the data in the StringMap doesn't look like the one in Azure. I tried String and Byte as datatype for the StringMap, but it doesn't helped.
I tried byte[] for ABZ_RowVersion, but then i got an exception in the callback method.
Then i tried Object for ABZ_RowVersion, that time i found out, that it is a StringMap, but nothing more.
Does anybody know, how to get the data from timestamp, i need it for comparison.
Thanks already
When you create a timestamp column in a table, it's essentially a varbinary(8) column. In the node SQL driver, it's mapped to a Buffer type (the usual node.js type used for binary data). The object which you see ({"0":0, "1":0, ..., "length":8}) is the way that a buffer is stringified into JSON. That representation doesn't map to the default byte array representation from the Gson serializer in Android (or to the byte[] in the managed code).
To be able to use timestamp columns, the first thing you need to do is to "teach" the serializer how to understand the format of the column returned by the server. You can do that with a JsonDeserializer<byte[]> class:
public class ByteArrayFromNodeBufferGsonSerializer
implements JsonDeserializer<byte[]> {
#Override
public byte[] deserialize(JsonElement element, Type type,
JsonDeserializationContext context) throws JsonParseException {
if (element == null || element.isJsonNull()) {
return null;
} else {
JsonObject jo = element.getAsJsonObject();
int len = jo.get("length").getAsInt();
byte[] result = new byte[len];
for (int i = 0; i < len; i++) {
String key = Integer.toString(i);
result[i] = jo.get(key).getAsByte();
}
return result;
}
}
}
Now you should be able to read data. There's still another problem, though. On insert and update operations, the value of the column is sent by the client, and SQL doesn't let you set them in them. So let's take this class:
public class Test {
#SerializedName("id")
private int mId;
#SerializedName("name")
private String mName;
#SerializedName("version")
private byte[] mVersion;
public int getId() { return mId; }
public void setId(int id) { this.mId = id; }
public String getName() { return mName; }
public void setName(String name) { this.mName = name; }
public byte[] getVersion() { return mVersion; }
public void setVersion(byte[] version) { this.mVersion = version; }
}
On the insert and update operations, the first thing we need to do in the server-side script is to remove that property from the object. And there's another issue: after the insert is done, the runtime doesn't return the rowversion property (i.e., it doesn't update the item variable. So we need to perform a lookup against the DB to retrieve that column as well:
function insert(item, user, request) {
delete item.version;
request.execute({
success: function() {
tables.current.lookup(item.id, {
success: function(inserted) {
request.respond(201, inserted);
}
});
}
});
}
And the same on update:
function update(item, user, request) {
delete item.version;
request.execute({
success: function() {
tables.current.lookup(item.id, {
success: function(updated) {
request.respond(200, updated);
}
});
}
});
}
Now, this definitely is a lot of work - the support for this type of column should be better. I've created a feature request in the UserVoice page at http://mobileservices.uservoice.com/forums/182281-feature-requests/suggestions/4670504-better-support-for-timestamp-columns, so feel free to vote it up to help the team prioritize it.

android XML parse into Hash map not working

I am getting the most bizzarre behavior with trying to parse an XML, I run through it step by step and all values are assigned and retrieved in order and then the object I create is added to a HashMap for easy look up, the problem is when I am done retrieving it all the HashMap has null values and the ones that aren't null are the value of the very last node that was read, I have walked through it over and over and it all seems correct, but when it's done loading the values in the HasMap look like:
[0] null
[1] NarrationItem#44e9d170
[2] null
[3] null
[4] NarrationItem#44e9d170
etc, etc.
The format of my XML files is:
<narrations>
<narration id="0" name="A" alias="a" >
<line text="This is a test."></line>
</narration>
<narration id="1" name="B" alias="b" >
<line text="This another a test."></line>
</narration>
<narration id="2" name="C" alias="c" >
<line text="This is STILL a test."></line>
</narration>
</narrations>
And my XML parsing method is follows:
public HashMap<String, NarrationItem> NarrationMap = new HashMap<String, NarrationItem>();
private void LoadNarrationsXML() {
NarrationItem i = new NarrationItem();
String line;
String s;
try {
// Get the Android-specific compiled XML parser.
XmlResourceParser xmlParser = this.getResources().getXml(R.xml.narrations);
while (xmlParser.getEventType() != XmlResourceParser.END_DOCUMENT) {
if (xmlParser.getEventType() == XmlResourceParser.START_TAG) {
s = xmlParser.getName();
if (s.equals("narration")) {
i.Clear();
i.ID = xmlParser.getAttributeIntValue(null, "id", 0);
i.Name = xmlParser.getAttributeValue(null, "name");
i.Alias = xmlParser.getAttributeValue(null, "alias");
} else if (s.equals("line")) {
line = xmlParser.getAttributeValue(null, "text");
i.Narration.add(line);
}
} else if (xmlParser.getEventType() == XmlResourceParser.END_TAG) {
s = xmlParser.getName();
if (s.equals("narration")) {
NarrationMap.put(i.Alias, i);
}
}
xmlParser.next();
}
xmlParser.close();
} catch (XmlPullParserException xppe) {
Log.e(TAG, "Failure of .getEventType or .next, probably bad file format");
xppe.toString();
} catch (IOException ioe) {
Log.e(TAG, "Unable to read resource file");
ioe.printStackTrace();
}
}
The NarrationItem object is a custom object defined as:
public class NarrationItem {
int ID;
String Name;
String Alias;
ArrayList<String> Narration = new ArrayList<String>();
public NarrationItem() { }
public void LoadNarration(int id, String name, String alias, ArrayList<String> narration) {
ID = id;
Name = name;
Alias = alias;
Narration.addAll(narration);// = narration;
}
public void Clear() {
ID = 0;
Name = "";
Alias = "";
Narration.clear();
}
}//End Narration
If someone could point out the problem I'd be very thankful I have sat here staring at this issue for hours.
You're only ever creating one NarrationItem object - you're then using a reference to that object as the value for multiple entries in the map. Don't do that. You need to understand that the map doesn't contain an object as the value - it contains a reference to an object.
You can probably fix this just by creating a new NarrationItem each time instead of calling Clear.
It's not clear how you're looking at the map to see those null values, but if you're using the debugger and looking at the internal data structure, you probably shouldn't really be doing that either - instead, step through the keys, values or entries, i.e. stick within the abstraction that HashMap is meant to support.

Saving ArrayLists in SQLite databases

So I want to save an ordered set of double values, and I want to be able to insert, retrieve or delete any value from this easily. As of such, I'm using a an ArrayList, where I define a class called Doubles to store the double values.
How do I store this arraylist in a record in an SQLite database? I mean...what should the columns type be? Can it be done?
You cannot insert ArrayList directly into Sqlite. Instead, you could use JSONObject (org.json.JSONObject) to insert the ArrayList. Please check below snippet, you can try something like below....
To insert,
JSONObject json = new JSONObject();
json.put("uniqueArrays", new JSONArray(items));
String arrayList = json.toString();
Insert the string into db.
To Read,
Read the string from db as String,
JSONObject json = new JSONObject(stringreadfromsqlite);
ArrayList items = json.optJSONArray("uniqueArrays");
To Insert :
ArrayList<String> inputArray=new ArrayList<String>();
Add Values to inputArray
Gson gson = new Gson();
String inputString= gson.toJson(inputArray);
System.out.println("inputString= " + inputString);
Use "inputString" to save the value of ArrayList<String> in SQLite Database
To retreive:
Get the String from the SQLiteDatabse what you saved and changed into ArrayList type like below:
outputarray is a String which is get from SQLiteDatabase for this example.
Type type = new TypeToken<ArrayList<String>>() {}.getType();
ArrayList<String> finalOutputString = gson.fromJson(outputarray, type);
In my case it was ArrayList of POJO classes Note
private String mNoteTitle;
private int mFingerIndex;
private Point mNoteCoordinates;
public Note(String noteTitle, int fingerIndex, Point noteCoordinates) {
this.mNoteTitle = noteTitle;
this.mFingerIndex = fingerIndex;
this.mNoteCoordinates = noteCoordinates;
}
As manual says JSONObject supports only following types: Object: a JSONObject, JSONArray, String, Boolean, Integer, Long, Double, NULL, or null. May not be NaNs or infinities. So, I should break my Note class into supported objects.
JSONObject json = new JSONObject();
JSONArray jsonArray = new JSONArray();
for(Note note: chordShape.getNotes()){
JSONObject singleNoteJsonObject = new JSONObject();
try {
singleNoteJsonObject.put(SHAPE_NOTE_TITLE, note.getNoteTitle());
singleNoteJsonObject.put(SHAPE_NOTE_FINGER_INDEX, note.getFingerIndex());
singleNoteJsonObject.put(SHAPE_NOTE_X, note.getNoteCoordinates().x);
singleNoteJsonObject.put(SHAPE_NOTE_Y, note.getNoteCoordinates().y);
} catch (JSONException e){
e.printStackTrace();
}
jsonArray.put(singleNoteJsonObject);
}
Pack created array into JSONObject.
try {
json.put(SHAPE_NOTES, jsonArray);
Log.i(TAG, json.toString());
} catch (JSONException e){
e.printStackTrace();
}
Create String.
String notesList = json.toString();
Put created String in ContentValues, cause in my case it's Android app
if(notesList.length() > 0){
contentValues.put(DatabaseHelper.SHAPE_NOTES_LIST, notesList);
}
And when i should read values from SQLite database.
ArrayList<Note> notes = new ArrayList<>();
while(cursor.moveToNext()){
JSONObject jsonNotes = null;
try {
jsonNotes = new JSONObject(cursor.getString(cursor.getColumnIndex(DatabaseHelper.SHAPE_NOTES_LIST)));
} catch (JSONException e){
e.printStackTrace();
}
if(jsonNotes != null){
Log.i(TAG, jsonNotes.toString());
JSONArray jsonArray = jsonNotes.optJSONArray(SHAPE_NOTES);
for(int i = 0; i < jsonArray.length(); i++){
Note note = null;
JSONObject arrayObject = null;
try {
arrayObject = jsonArray.getJSONObject(i);
} catch (JSONException e){
e.printStackTrace();
}
if(arrayObject != null){
try {
note = new Note(
arrayObject.getString(SHAPE_NOTE_TITLE),
arrayObject.getInt(SHAPE_NOTE_FINGER_INDEX),
new Point(
arrayObject.getInt(SHAPE_NOTE_X),
arrayObject.getInt(SHAPE_NOTE_Y)
)
);
} catch (JSONException e){
e.printStackTrace();
}
}
if(note != null){
notes.add(note);
}
}
}
}
cursor.close();
I suggest going through all 3 Notepad tutorials you want to store the values your storing to a database table. you don't store the actual array directly into the database just the data. but you shouldn't actually need to use an array at all instead of adding a new item to the array instead call your db insert method
I've needed to do something similar in my application, where I have a custom class (Foo, Bar, etc.) and I have an ArrayList of foo, bar, etc. that I persist to SQL. My knowledge of SQL isn't strong, but I'll explain my approach here in case it helps.
My understanding is that to store any kind of object, you need to define a particular table for that object type, where the table has separate columns representing the primitive types within that object. Furthermore, to persist and retrieve an ArrayList of those objects, you'll use one table row per ArrayList entry, and iterate over in a loop to store and retrieve.
There are ArrayLists of several custom classes in my application that I wanted to persist to DB. So, to make things tidy (well, to me at least -- I'm still a relatively new Java / Android programmer, so take this with a pinch of salt) I decided to implement a kind of "SQL Serializable Interface" that my DB-persistable objects must implement. Each object (Foo, Bar, etc.) that can be persisted to DB must implement:
A public static final TABLE_NAME string, the name of the SQL DB table used for this object type.
A public static final TABLE_CREATE_STRING, a complete SQL instruction to create the table for this object.
A constructor method to populate its member variables from a ContentValues object.
A 'get' method to populate a ContentValues from its member variables.
So, say I have ArrayLists of objects Foo and Bar. When the DB is first created, within my DB helper class I call Foo.TABLE_CREATE_STRING, Bar.TABLE_CREATE_STRING, etc. to create the tables for those objects.
To populate my ArrayList, I use something like:
cursor = dbh.retrieve(Foo.TABLE_NAME);
if(!cursor.moveToFirst()){
return false
}
do{
DatabaseUtils.cursorRowToContentValues(cursor, vales);
FooArrayList.add( new Foo(values) );
} while( cursor.moveToNext() );
Create a dbHelper class which has an inner class and pretty much whatever the notepad tutorial says. The class must be having an insertion method somthing like this :-
public long insertRows(ContentValues values, String tableName) {
long val = myDatabase.insert(tableName, null, values);
return val;
}
This method will then add values into the table row.
After that you can call this method from your main activity and since you are using cursor i believe you will call the method in a for loop
for(i=0;list.length();i++) // or may be its list.size :P
{
// Call the method here
}
and keep adding value in the database by calling the method in for loop

Android, Null Pointer Exception to Data that isn't null

I'm writing an app for android that needs to parse data from an XML file. I've never come across an error like this that is so impossibly hard to track down. Or maybe my brain just stopped working. That happens. XML file is of the form:
<?xml version="1.0" encoding="iso-8859-1"?>
<memberRoster>
<agent>
<agentInfo1>...</agentInfo1>
<agentInfo2>...</agentInfo2>
...
</agent>
<agent>
...
</agent>
...
</memberRoster>
So far it's working well, except for some random bits of fun!
Every now and then it will throw a NullPointerException. I did some more digging and found out that there are THREE "agents" (out of 800) with "supposedly" null data. I checked the XML file and the data is there, there are no illegal characters, etc. It is the same three "agents" every time. The program parses other entries before and after these "null" "agents". Also of note is that not all "agentInfo" fields in the ArrayList come up null; example, one of the entries has 7 of the 8 entries as null, with the 8th one non-null, another has only one null with the last 7 non-null.
I'm parsing the data in to an ArrayList from the XML file, and like I mentioned before, it works flawlessly until it comes to those three specific entries in the XML file.
I'm sorry I can't give much more info than that, the data is sensitive to our members.
EDIT:
Sorry! I knew I was forgetting something! :)
Some code from my XMLHandler.java class:
public void characters(char[] ch, int start, int length)
if(this.in_mr_agentNrdsId) {
agent[0] = ch.toString();
}
else if(this.in_mr_agentFirstName) {
agent[1] = ch.toString();
}
else if(this.in_mr_agentLastName) {
agent[2] = ch.toString();
}
else if(this.in_mr_agentPhone) {
agent[3] = ch.toString();
}
else if(this.in_mr_agentEmail) {
agent[4] = ch.toString();
}
else if(this.in_mr_agentOfficeName) {
agent[5] = ch.toString();
}
else if(this.in_mr_agentOfficePhone) {
agent[6] = ch.toString();
}
else if(this.in_mr_agentType) {
agent[7] = ch.toString();
pds.setMemberRoster(agent);
agent = new String[8];
}
PDS is an object of type ParsedDataSet, which is just a simple class containing the ArrayList objects and a few getter and setter methods:
public class ParsedDataSet {
private ArrayList agentOpenHouses = new ArrayList();
private ArrayList calendarOfEvents = new ArrayList();
private ArrayList latestStatistics = new ArrayList();
private ArrayList memberRoster = new ArrayList();
public ArrayList<String[]> getAgentOpenHouses() {
return agentOpenHouses;
}
public ArrayList<String[]> getCalendarOfEvents() {
return calendarOfEvents;
}
public ArrayList<String[]> getLatestStatistics() {
return latestStatistics;
}
public ArrayList<String[]> getMemberRoster() {
return memberRoster;
}
public void setAgentOpenHouses(String[] agentOpenHousesItem) {
this.agentOpenHouses.add(agentOpenHousesItem);
}
public void setCalendarOfEvents(String[] calendarOfEventsItem) {
this.calendarOfEvents.add(calendarOfEventsItem);
}
public void setLatestStatistics(String[] latestStatisticsItem) {
this.latestStatistics.add(latestStatisticsItem);
}
public void setMemberRoster(String[] memberRosterItem) {
this.memberRoster.add(memberRosterItem);
}
} // end class ParsedDataSet
You could throw an if statement into your assignements and reassign any caught 'NULL' or empty strings into a zero value or just reassign as variable = "" in your code.
For example:
if (agentInfo1 == NULL) {
agentInfo1 = "" || agentInfo1 = 0; //Depending on what your variables are
}
Try putting try catch loop in code to find where the error is happening, then, pinpoint the exact part of code that is giving this error, there do null checks before proceeding. This is based on best practices of software development, rather than a fix for you.
Alternatively, you can makes sure on server side that there are no "null" values, maybe by giving dummy value like "EMPTY_STRING". This is especially relevant if your app is already shipped and you cant make any client code changes.

Categories

Resources