Android + toString - android

Can anybody please tell what toString in Android is for and how it can be used?
As example would be highly appreciated.

toString is not specific to android. Its a method in java's Object class, which is the superclass of every java object. 'toString' is meant for returning textual representation of an object. This is generally overridden by java classes to create a human readable string to represent that object.
Apart from many other uses, it is widely used for logging purpose so as to print the object in a readable format. Appending an object with string automatically calls the toString() of that object e.g. "abc" + myObject will invoke 'toString' of myObject and append the returned value to "abc"
A good example of toString implementation would look like -
#Override
public String toString() {
return new StringBuilder()
.append("{Address:")
.append(" street=").append(street)
.append(", pincode=").append(pincode)
.append("}").toString();
}

Its the same as in normal Java...
I use it for debugging like this:
class MyClass {
var myVar;
var myOtherVar;
public String toString() {
return "myVar: " + myVar + " | myOtherVar: " + myOtherVar;
}
}
with Log.d("TAG", myClassObject.toString()); I can log what my object contains...
thats just one of countless possibilities.

class Account {
public final String name;
public final String email;
public Account(String name, String email) {
this.name = name;
this.email = email;
}
#Override
public String toString() {
return new Gson().toJson(this);
}
}

It's not like Java. Override example:
#Override
public String toString()
{
return new StringBuffer()
.append("[Museum]-")
.append(name)
.append(" Lat:")
.append(lat)
.append(" Lon: ")
.append(lon).toString();
}
And then usage of the method is
Log.i(LOG_TAG, museum.toString()); // Instead of just "museum"

Related

Firebase ServerValue.TIMESTAMP in Java data models objects

I'm new to Firebase, and I've been really enjoying it so far. I'm running into a problem; I'm using the FirebaseListAdapter similar to the tutorial outline here: https://github.com/firebase/AndroidChat
To use the FirebaseListAdapter, I need to use data model objects (to get the automatic binding to work nicely). The problem is I also want to keep a timestamp value with that model object, and I want to get the timestamp from the Firebase server.
What I have currently that is NOT working is a class DataModelObject (similar to com.firebase.androidchat.Chat in the demo example) with a constructor like :
DataModelObject(String data1, String data2, Map enQTimeStamp)
which I then try to use like this:
DataModelObject dmo = new DataModelObject ("foo", "bar", ServerValue.TIMESTAMP);
myFirebaseRef.push().setValue(dmo);
This causes a JsonMappingException when I try to run that code. I found a code snippet here :
https://www.firebase.com/blog/2015-02-11-firebase-unique-identifiers.html
But it's worthwhile to note that on line 4 of the Android code example, that will cause a compile time error (as he is trying to put ServerValue.TIMESTAMP into a Map, and TIMESTAMP is a Map itself)
What is the right way to do this and maintain compatibility with FirebaseListAdapter?
This sounds similar to this question: When making a POJO in Firebase, can you use ServerValue.TIMESTAMP?
When creating POJOs used to store/retrieve data apart from the default empty constructor I usually use a constructor similar to this:
Param param1;
Param param2;
HashMap<String, Object> timestampCreated;
//required empty constructor
public DataObject(){}
public DataObject(Param param1, Param param2) {
this.param1 = param1;
this.param2 = param2;
HashMap<String, Object> timestampNow = new HashMap<>();
timestampNow.put("timestamp", ServerValue.TIMESTAMP);
this.timestampCreated = timestampNow;
}
Be sure to include a getter for the HashMap<> used to store the Timestamp:
public HashMap<String, Object> getTimestampCreated(){
return timestampCreated;
}
Then use the #Exclude annotation to create a getter that you can use in your code to get the value of the timestamp if you need it. The #Exclude annotation will cause Firebase to ignore this getter and not look for a corresponding property
#Exclude
public long getTimestampCreatedLong(){
return (long)timestampCreated.get("timestamp");
}
Here's how I do it
//member variable
Object createdTimestamp;
public YourConstructor(){
createdTimestamp = ServerValue.TIMESTAMP
}
#Exclude
public long getCreatedTimestampLong(){
return (long)createdTimestamp;
}
Your db object should include these:
public class FirebaseDbObject {
private final Object timestamp = ServerValue.TIMESTAMP;
//........
//........
Object getTimestamp() {
return timestamp;
}
#Exclude
public long timestamp() {
return (long) timestamp;
}
}
This will add an extra field called "timestamp" to your object.
Edit: The answer posted by MobileMon is not fully correct as it does not have getter method. This is the complete and correct answer.
Kotlin provides an easy way to achieve this by data classes. You can create it like
data class FirebaseRequestModel(
var start_time: Any = ServerValue.TIMESTAMP,
var stop_time: Long = 0,
var total_time: Long = 0,
)
and use it directly by
val firebaseModel = FirebaseRequestModel()
firebaseRef.setValue(firebaseModel)
This will get default values from data class.
Or even you can initiate your own values by
val firebaseModel = FirebaseRequestModel(ServerValue.TIMESTAMP, 2134, 0)
firebaseRef.setValue(firebaseModel)
Similar to Urgurcan's answer, but a bit cleaner so the caller doesn't have trouble guessing between getTimestamp vs timestamp.
public class FirebaseDbObject {
private Object timestamp = ServerValue.TIMESTAMP;
//........
//........
#PropertyName("timestamp")
Object getRawTimestamp() {
return timestamp;
}
#Exclude
public long getTimestamp() {
return (long) timestamp;
}
}
You can do it:
public class MyTimeStamp {
private Object timestamp;
public MyTimeStamp() {
}
public Object getTimestamp() {
return timestamp;
}
public void setTimestamp(Object timestamp) {
this.timestamp = timestamp;
}
}
And so:
public static void start(Context context) {
MyTimeStamp timeStamp = new MyTimeStamp();
timeStamp.setTimestamp(ServerValue.TIMESTAMP);
Log.d(TAG, "start: ", timeStamp.getTimestamp().toString());
}

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.

GSON does not cast Json string to class

I am trying to convert JSonObject string to some specific classes.
MyClass mc= new Gson().fromJson(jo.toString(),MyClass.class);
After this step all values of mc is null.
Value of the jo.toString() :
{
"__type":"MyClass:#MyProject.Model",
"ID":1,
"Comment":"First Record",
"SubClassID":534,
"Active":true,
"Date":"\/Date(1323087840000+0200)\/"
}
MyClass.java has attributes ID, Comment...
Thanks Regards...
MyClass.Java:
public class MyClass extends ABase
{
private String _Comment;
public String getComment(){
return _Comment;
}
public void setComment(String value){
_Comment = value;
}
private Integer _ID;
public Integer getID(){
return _ID;
}
public void setID(Integer value){
_ID = value;
}
private java.util.Date _Date;
public java.util.Date getDate(){
return _Date;
}
public void setDate(java.util.Date value){
_Date = value;
}
}
The problem is that the JSON element names do not match the Java field names, and no explicit alternative name-mapping configuration was provided to Gson.
Possible Solutions:
Change the Java field names to exactly match the JSON element names. This of course isn't always possible, e.g., when the JSON element names include characters or formats not valid for Java field names.
Change the JSON element names to exactly match the Java field names. This of course isn't always possible, e.g., when the JSON is from a third party.
Provide Gson with name-mappings, using either the #SerializedName annotation, or a FieldNamingPolicy.

JSON parsing using GSON - Setting up class hierarchy

I can't seem to wrap my head around how to setup my class hierarchy for JSON conversion using GSON.
My JSON looks like:
{
"Users": {
"id": 1,
"name": "Jim",
"location": "Huntsville"
}
}
My User List class looks like:
public class UserList {
public static List<User> Users;
#SuppressWarnings("static-access")
public void setUserList(List<User> userList){
this.Users = userList;
}
public List<User> getUserList(){
return Users;
}
}
and lastly a user class that looks like this:
public class User {
private int id;
private String name;
private String location;
public int getId(){
return id;
}
public String getName(){
return name;
}
public String getLocation(){
return location;
}
public String toString(){
return("User: [id=" + id + "], [name=" + name + "], [location=" + location + "]");
}
}
Anyone mind giving me a shove in the right direction? I'd appreciate it!
EDIT:
Forgot to show my parsing code.. (Just reading a sample JSON file from SDCard)
BufferedReader br = new BufferedReader(new FileReader(Environment.getExternalStorageDirectory() + "/user.json"));
UserList userList = gson.fromJson(br, UserList.class);
are you sure your example JSON is correct?
It does not seem to be a list of things, just one user is defined.
Furthermore, your getter and setters for Users, should be following the get/set pattern and be called
public List<User> getUsers()
public void setUsers(List<User> users)
Also, you can follow the Java convention of small case and instruct Gson to use a different casing.
Assuming that you only have one entry of Users in your JSON. This would let you parse the snippit you provided, if you change the Users property into User not a list.
#SerializedName("Users")
private User user;
So if you want a list of users you should find that in the json, this should let you parse it as a list, !note that you need to have objects, which are enclosed, like:
{"users" : [{id:"one"}, ...]}
As pointed out in the comments.

android function in class throws java.lang.NullPointerException

I've made a class which holds some string and integers, in that class I made a function to convert the data in the class in to a readable string;
public String GetConditions() {
String BigString = null;
String eol = System.getProperty("line.separator");
try {
BigString += "Depth: " + ci(Depth) + eol;
and so on...
Because I have to convert many integers, I made an extra function to convert a integer to a string;
public String ci(Integer i) {
// convert integer to string
if (i != null) {
String a = new Integer(i).toString();
return a;
} else {
return "n/a";
}
}
This throws a NullPointerException exception on return a. I'm quite new to Java, this is probally a noob question... Sorry about, thanks in advance!
There is a much simpler way to convert an Integer to a String: use String#valueOf(int).
public String ci(Integer i)
{
return i == null ? "n/a" : String.valueOf(i);
}
Try converting the Integer you pass in your method to string, instead of instantiating a new one.
You can do it straight forward like:
String a = i.toString();
or
String a = Integer.toString(i.intValue());
Thanks guys, but I found the problem, I've tried to add something to a string which was 'null' , this line:
String BigString = null;

Categories

Resources