JSONArray.getString(1); where ["name",null] is the json array, throws a JSONArray[1] not a string exception only when proguard is enabled.
Am I missing something in my proguard rules?
Did you try these methods:
/**
* Returns the value at {#code index} if it exists, coercing it if
* necessary. Returns the empty string if no such value exists.
*/
public String optString(int index)
or
/**
* Returns the value at {#code index} if it exists, coercing it if
* necessary. Returns {#code fallback} if no such value exists.
*/
public String optString(int index, String fallback)
Seem like does not return null for String
Related
I have 3 columns in my Parse class, FOOD1, FOOD2 and FOOD3.
it is optional for the user if they choose 0,1,2 or 3 Foods they like, i save the foods in these columns. This process will be repeated.
For every loop i want to set all these fields on null/undefined so i can simply see if they choose something after selection.
But when one of the fields eg. FOOD1 is filled in the database, i cant clear the value of it.
i tried:
final ParseQuery queryusername = ParseQuery.getQuery("Usernames");
queryusername.whereContains("names",db.getUsername());
try {
ParseObject p = queryusername.getFirst();
System.out.println("parseobject:"+p);
//make fields empty
p.put("Food1",null); //Error
p.put("Food2",null);
p.put("Food3",null);
}catch(){}
the error is:
java.lang.IllegalArgumentException: value may not be null.
how can i clear the field?
Parse object provides remove(). Pass it the key to remove, e.g.
p.remove("Food1");
p.remove("Food2");
p.remove("Food3");
It seems that Parse SDK has checks for null.
From the source
/**
* Add a key-value pair to this object. It is recommended to name keys in
* <code>camelCaseLikeThis</code>.
*
* #param key
* Keys must be alphanumerical plus underscore, and start with a letter.
* #param value
* Values may be numerical, {#link String}, {#link JSONObject}, {#link JSONArray},
* {#link JSONObject#NULL}, or other {#code ParseObject}s. value may not be {#code null}.
*/
Why do you need to set it to NULL? You can always use empty String or some constant integer or finally JSONObject.NULL.
Or use p.remove as in the answer by #danh
The answer of https://stackoverflow.com/users/294949/danh works. You must save the object:
p.remove("Food1");
p.remove("Food2");
p.remove("Food3");
try {
p.save();
}
catch (ParseException e) {
}
When creating a live event from my android application, I can't seem to add any tags for the event. The youtube api uses the BroadcastSnippet class to set all basic info for a new live event. The class BroadcastSnippet doesn't contain a tags field. However, when I create a live event from my web browser I can add tags to the new live event. Does anyone know how I can add tags to a live event using the youtube api programmatically from my android phone?
live broadcast snippet class:
public final class LiveBroadcastSnippet extends com.google.api.client.json.GenericJson {
/**
* The date and time that the broadcast actually ended. This information is only available once
* the broadcast's state is complete. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private com.google.api.client.util.DateTime actualEndTime;
/**
* The date and time that the broadcast actually started. This information is only available once
* the broadcast's state is live. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private com.google.api.client.util.DateTime actualStartTime;
/**
* The ID that YouTube uses to uniquely identify the channel that is publishing the broadcast.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private java.lang.String channelId;
/**
* The broadcast's description. As with the title, you can set this field by modifying the
* broadcast resource or by setting the description field of the corresponding video resource.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private java.lang.String description;
/**
* The date and time that the broadcast was added to YouTube's live broadcast schedule. The value
* is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ) format.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private com.google.api.client.util.DateTime publishedAt;
/**
* The date and time that the broadcast is scheduled to end. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private com.google.api.client.util.DateTime scheduledEndTime;
/**
* The date and time that the broadcast is scheduled to start. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private com.google.api.client.util.DateTime scheduledStartTime;
/**
* A map of thumbnail images associated with the broadcast. For each nested object in this object,
* the key is the name of the thumbnail image, and the value is an object that contains other
* information about the thumbnail.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private ThumbnailDetails thumbnails;
/**
* The broadcast's title. Note that the broadcast represents exactly one YouTube video. You can
* set this field by modifying the broadcast resource or by setting the title field of the
* corresponding video resource.
* The value may be {#code null}.
*/
#com.google.api.client.util.Key
private java.lang.String title;
/**
* The date and time that the broadcast actually ended. This information is only available once
* the broadcast's state is complete. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* #return value or {#code null} for none
*/
public com.google.api.client.util.DateTime getActualEndTime() {
return actualEndTime;
}
/**
* The date and time that the broadcast actually ended. This information is only available once
* the broadcast's state is complete. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* #param actualEndTime actualEndTime or {#code null} for none
*/
public LiveBroadcastSnippet setActualEndTime(com.google.api.client.util.DateTime actualEndTime) {
this.actualEndTime = actualEndTime;
return this;
}
/**
* The date and time that the broadcast actually started. This information is only available once
* the broadcast's state is live. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* #return value or {#code null} for none
*/
public com.google.api.client.util.DateTime getActualStartTime() {
return actualStartTime;
}
/**
* The date and time that the broadcast actually started. This information is only available once
* the broadcast's state is live. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ)
* format.
* #param actualStartTime actualStartTime or {#code null} for none
*/
public LiveBroadcastSnippet setActualStartTime(com.google.api.client.util.DateTime actualStartTime) {
this.actualStartTime = actualStartTime;
return this;
}
/**
* The ID that YouTube uses to uniquely identify the channel that is publishing the broadcast.
* #return value or {#code null} for none
*/
public java.lang.String getChannelId() {
return channelId;
}
/**
* The ID that YouTube uses to uniquely identify the channel that is publishing the broadcast.
* #param channelId channelId or {#code null} for none
*/
public LiveBroadcastSnippet setChannelId(java.lang.String channelId) {
this.channelId = channelId;
return this;
}
/**
* The broadcast's description. As with the title, you can set this field by modifying the
* broadcast resource or by setting the description field of the corresponding video resource.
* #return value or {#code null} for none
*/
public java.lang.String getDescription() {
return description;
}
/**
* The broadcast's description. As with the title, you can set this field by modifying the
* broadcast resource or by setting the description field of the corresponding video resource.
* #param description description or {#code null} for none
*/
public LiveBroadcastSnippet setDescription(java.lang.String description) {
this.description = description;
return this;
}
/**
* The date and time that the broadcast was added to YouTube's live broadcast schedule. The value
* is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ) format.
* #return value or {#code null} for none
*/
public com.google.api.client.util.DateTime getPublishedAt() {
return publishedAt;
}
/**
* The date and time that the broadcast was added to YouTube's live broadcast schedule. The value
* is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ) format.
* #param publishedAt publishedAt or {#code null} for none
*/
public LiveBroadcastSnippet setPublishedAt(com.google.api.client.util.DateTime publishedAt) {
this.publishedAt = publishedAt;
return this;
}
/**
* The date and time that the broadcast is scheduled to end. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* #return value or {#code null} for none
*/
public com.google.api.client.util.DateTime getScheduledEndTime() {
return scheduledEndTime;
}
/**
* The date and time that the broadcast is scheduled to end. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* #param scheduledEndTime scheduledEndTime or {#code null} for none
*/
public LiveBroadcastSnippet setScheduledEndTime(com.google.api.client.util.DateTime scheduledEndTime) {
this.scheduledEndTime = scheduledEndTime;
return this;
}
/**
* The date and time that the broadcast is scheduled to start. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* #return value or {#code null} for none
*/
public com.google.api.client.util.DateTime getScheduledStartTime() {
return scheduledStartTime;
}
/**
* The date and time that the broadcast is scheduled to start. The value is specified in ISO 8601
* (YYYY-MM-DDThh:mm:ss.sZ) format.
* #param scheduledStartTime scheduledStartTime or {#code null} for none
*/
public LiveBroadcastSnippet setScheduledStartTime(com.google.api.client.util.DateTime scheduledStartTime) {
this.scheduledStartTime = scheduledStartTime;
return this;
}
/**
* A map of thumbnail images associated with the broadcast. For each nested object in this object,
* the key is the name of the thumbnail image, and the value is an object that contains other
* information about the thumbnail.
* #return value or {#code null} for none
*/
public ThumbnailDetails getThumbnails() {
return thumbnails;
}
/**
* A map of thumbnail images associated with the broadcast. For each nested object in this object,
* the key is the name of the thumbnail image, and the value is an object that contains other
* information about the thumbnail.
* #param thumbnails thumbnails or {#code null} for none
*/
public LiveBroadcastSnippet setThumbnails(ThumbnailDetails thumbnails) {
this.thumbnails = thumbnails;
return this;
}
/**
* The broadcast's title. Note that the broadcast represents exactly one YouTube video. You can
* set this field by modifying the broadcast resource or by setting the title field of the
* corresponding video resource.
* #return value or {#code null} for none
*/
public java.lang.String getTitle() {
return title;
}
/**
* The broadcast's title. Note that the broadcast represents exactly one YouTube video. You can
* set this field by modifying the broadcast resource or by setting the title field of the
* corresponding video resource.
* #param title title or {#code null} for none
*/
public LiveBroadcastSnippet setTitle(java.lang.String title) {
this.title = title;
return this;
}
#Override
public LiveBroadcastSnippet set(String fieldName, Object value) {
return (LiveBroadcastSnippet) super.set(fieldName, value);
}
#Override
public LiveBroadcastSnippet clone() {
return (LiveBroadcastSnippet) super.clone();
}
}
when we want to get value of a key we should do something like this.
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "defVal");
in getString document wrote.
/**
* Retrieve a set of String values from the preferences.
*
* <p>Note that you <em>must not</em> modify the set instance returned
* by this call. The consistency of the stored data is not guaranteed
* if you do, nor is your ability to modify the instance at all.
*
* #param key The name of the preference to retrieve.
* **#param defValues Values to return if this preference does not** exist.
*
* #return Returns the preference values if they exist, or defValues.
* Throws ClassCastException if there is a preference with this name
* that is not a Set.
*
* #throws ClassCastException
*/
now i have a question why default value argument must exist!?
Because the preference may not have been saved yet. It's easier to deal with this than to write:
String value;
if (sharedPreferences.contains(PREFS_KEY)) {
value = sharedPreferences.getString(PREFS_KEY);
} else {
value = "defaultValue";
}
The answer is in the documentation. What if you call
String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "defVal");
before saving any value? It will have to return null, which in turn can create problems like NullPointerException. So, default value is used as a precaution.
I have this problem of recreating an array of a custom data type after it was written to a parcel.
playerwear is declared as such:
private Wearable playerWear[] = new Wearable[5];
This is the lines that write it to a parcel in the parent class.
It is an array of type Wearable with 5 elements
parcel.writeArray(playerWear);
This is the line that reads it from the Parcel (temp is an empty data element of the parent and has all elements filled in the same fashion as bellow. All others are working)
temp.playerWear = (Wearable[])source.readArray(Wearable.class.getClassLoader());
Here is the code of the Parcel Interface that are defined in the Wearable datatype:
#Override
public int describeContents()
{
return 0;
}
/**
* This is the main method of the Parcelable Interface. This packs everything
* up into the parcel that will be used in the next activity
* #param parcel the parcel that will be passed to the next activity
* #param i used to keep track of the size...I think
*/
#Override
public void writeToParcel(Parcel parcel, int i)
{
parcel.writeString(slotName);
parcel.writeParcelable(heldItem, i);
if (holdingItem)
parcel.writeString("True");
else
parcel.writeString("False");
}
/**
* This is the method that takes the passed parcel and rebuilds it so that it can be used
* #param source the passed parcel
* #return the reconstructed data type
*/
public static Wearable recreateParcel(Parcel source)
{
Wearable temp = new Wearable();
temp.slotName = source.readString();
temp.heldItem = (Item) source.readParcelable(Item.class.getClassLoader());
String bool = source.readString();
if(bool.equals("True"))
temp.holdingItem = true;
else
temp.holdingItem = false;
return temp;
}
/**
* Not truly sure what this is but I think this is similar to the classLoader
*/
public static final Parcelable.Creator CREATOR = new Parcelable.Creator()
{
/**
* Calls the method that I created to recreate the Data type
* #param in the passed parcel
* #return s the return of the recreateParcel method
*/
public Wearable createFromParcel(Parcel in)
{
return recreateParcel(in);
}
/**
* Called if the custom data type is in an array
* #param size the size of the array. Used to figure out how many elements are needed
* #return an Array of the Data type
*/
public Wearable[] newArray(int size)
{
return new Wearable[size];
}
};
Lastly this is the error that it is giving me,
Caused by: java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.rtbd.storytime.Wearable[]
Please post if I forgot any vital information that is needed to solve this problem.
Thanks!
After doing a lot more research I found the answer at:
Read & writing arrays of Parcelable objects
You don't want to write as a parcelableArray or as a Array you want to write it as a TypedArray and then call the CREATOR of the data type in the createTypedArray method.
I have a SparseArray<myObject> and want to store it in bundle in onSaveInstanceState method in my activity and restore it in oncreate. I found putSparseParcelableArray method for put SparseArray in bundle and did this in onSaveInstanceState method:
bundle.putSparseParcelableArray("mySparseArray", mySparseArray);
But eclips shows this error:
The method putSparseParcelableArray(String, SparseArray<? extends Parcelable>) in the type Bundle is not applicable for the arguments (String, SparseArray<myObject>)
And the quick fix is casting argument mySparsArray to SparseArray<? extends Parcelable>, but if I do so and get it in onCreate method:
mySparseArray = (SparseArray<myObject>) savedInstanceState.getSparseParcelableArray("mySparseArray");
It gets this error:
Cannot cast from SparseArray<Parcelable> to SparseArray<myObject>
If this way is wrong, what is the solution for put mySparseArray in bundle?
Any help would be much appreciated.
You can extend SparsArray to imlement a Serializable as use it:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import android.util.SparseArray;
/**
* #author Asaf Pinhassi www.mobiledev.co.il
* #param <E>
*
*/
public class SerializableSparseArray<E> extends SparseArray<E> implements Serializable{
private static final long serialVersionUID = 824056059663678000L;
public SerializableSparseArray(int capacity){
super(capacity);
}
public SerializableSparseArray(){
super();
}
/**
* This method is private but it is called using reflection by java
* serialization mechanism. It overwrites the default object serialization.
*
* <br/><br/><b>IMPORTANT</b>
* The access modifier for this method MUST be set to <b>private</b> otherwise {#link java.io.StreamCorruptedException}
* will be thrown.
*
* #param oos
* the stream the data is stored into
* #throws IOException
* an exception that might occur during data storing
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
Object[] data = new Object[size()];
for (int i=data.length-1;i>=0;i--){
Object[] pair = {keyAt(i),valueAt(i)};
data[i] = pair;
}
oos.writeObject(data);
}
/**
* This method is private but it is called using reflection by java
* serialization mechanism. It overwrites the default object serialization.
*
* <br/><br/><b>IMPORTANT</b>
* The access modifier for this method MUST be set to <b>private</b> otherwise {#link java.io.StreamCorruptedException}
* will be thrown.
*
* #param oos
* the stream the data is read from
* #throws IOException
* an exception that might occur during data reading
* #throws ClassNotFoundException
* this exception will be raised when a class is read that is
* not known to the current ClassLoader
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
Object[] data = (Object[]) ois.readObject();
for (int i=data.length-1;i>=0;i--){
Object[] pair = (Object[]) data[i];
this.append((Integer)pair[0],(E)pair[1]);
}
return;
}
}
Your class should implement Parcelable and should have a static final member variable called CREATOR of type Parcelable.Creator<myObject>.