Android/Java, Cloud Firestore .toObject method not working - android

I develop an Android app which interacts with Google Firebase Cloud Firestore. To get data from Firestore, I use addOnCompleteListener with DocumentSnapshot.toObject() method. However, method toObject() seems not to work properly because it doesn't transmit data from snapshot to object.
Goal.class
#Entity
public class Goal {
// private variables
#PrimaryKey (autoGenerate = true)
private int id;
private String remoteId;
private int goalPos;
private String goalName;
private int goalCategory;
private String goalDescription;
private int goalColor;
private int goalFrequency;
private long goalFrequencyCode;
private boolean goalRewardType;
private double goalReward;
private int activated;
private boolean isSynced;
// constructor
public Goal() {
remoteId = "";
goalPos = 0;
goalName = "";
goalCategory = 15;
goalDescription = "";
goalColor = R.color.cat_Black;
goalFrequency = 0; // 0=Daily, 1=Weekly, 2=Monthly
goalFrequencyCode = 1111111111; // 1111111.111 - Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday; first of month, middle of month, last of month
goalRewardType = false; // false = standard, true = individual
activated = 1; // 0=No, 1=Yes
isSynced = false;
}
// getter and setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRemoteId() {
return remoteId;
}
public void setRemoteId(String remoteId) {
this.remoteId = remoteId;
}
public int getGoalPos() {
return goalPos;
}
public void setGoalPos(int goalPos) {
this.goalPos = goalPos;
}
public String getGoalName() {
return goalName;
}
public void setGoalName(String goalName) {
this.goalName = goalName;
}
public int getGoalCategory() {
return goalCategory;
}
public void setGoalCategory(int goalCategory) {
this.goalCategory = goalCategory;
}
public String getGoalDescription() {
return goalDescription;
}
public void setGoalDescription(String goalDescription) {
this.goalDescription = goalDescription;
}
public int getGoalColor() {
return goalColor;
}
public void setGoalColor(int goalColor) {
this.goalColor = goalColor;
}
public int getGoalFrequency() {
return goalFrequency;
}
public void setGoalFrequency(int goalFrequency) {
this.goalFrequency = goalFrequency;
}
public long getGoalFrequencyCode() {
return goalFrequencyCode;
}
public void setGoalFrequencyCode(long goalFrequencyCode) {
this.goalFrequencyCode = goalFrequencyCode;
}
public LinkedList<Integer> getGoalFrequencyCodeAsList() {
LinkedList<Integer> stack = new LinkedList<>();
long number = goalFrequencyCode;
while (number > 0) {
long longTempMod = number % 10;
int intTempMod = (int) longTempMod;
stack.push(intTempMod);
number = number / 10;
}
return stack;
}
public void setGoalFrequencyCodeFromList(LinkedList<Integer> stack) {
double number = 0;
for (int j = 0; j < stack.size(); j++) {
Log.d(String.valueOf(j), String.valueOf(stack.get(j)));
}
if (stack.size() <= 1) {
goalFrequencyCode = 1111111111;
} else {
for (int i = 0; i < stack.size(); i++) {
Log.d(String.valueOf(stack.get(i)), String.valueOf(number));
number = number + (stack.get(i) * Math.pow(10, (stack.size() - 1 - i)));
}
Log.d("Sent from Goal - number", String.valueOf(number));
goalFrequencyCode = (long) number;
Log.d("Sent from Goal - long", String.valueOf(goalFrequencyCode));
}
}
public boolean getGoalRewardType() {
return goalRewardType;
}
public void setGoalRewardType(boolean goalRewardType) {
this.goalRewardType = goalRewardType;
}
public double getGoalReward() {
return goalReward;
}
public void setGoalReward(double goalReward) {
this.goalReward = goalReward;
}
public int getActivated() {
return activated;
}
public void setActivated(int activated) {
this.activated = activated;
}
public boolean getIsSynced() {
return isSynced;
}
public void setIsSynced(boolean isSynced) {
this.isSynced = isSynced;
}
#Override
public String toString() {
return "Goal{" +
"id=" + id +
", remoteId='" + remoteId + '\'' +
", goalPos=" + goalPos +
", goalName='" + goalName + '\'' +
", goalCategory=" + goalCategory +
", goalDescription='" + goalDescription + '\'' +
", goalColor=" + goalColor +
", goalFrequency=" + goalFrequency +
", goalFrequencyCode=" + goalFrequencyCode +
", goalRewardType=" + goalRewardType +
", goalReward=" + goalReward +
", activated=" + activated +
", isSynced=" + isSynced +
'}';
}
}
FirebaseService.class
public LiveData<ApiResponse<List<Goal>>> getGoals() {
final MutableLiveData<ApiResponse<List<Goal>>> list = new MutableLiveData<>();
if (mAuth.getCurrentUser() != null) {
userId = mAuth.getCurrentUser().getUid();
colRefGoals = firestore.collection(userId).document("data").collection("goals");
colRefGoals
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Goal> goalsList = new ArrayList<Goal>();
for (DocumentSnapshot documentSnapshot : task.getResult()) {
Log.d("firebaseService", "DocumentSnapshop.getData: " + documentSnapshot.getData());
Goal goal = documentSnapshot.toObject(Goal.class);
Log.d("firebaseService", "DocumentSnapshot.toObject(Goal.class): " + goal.toString());
goalsList.add(goal);
}
ApiResponse<List<Goal>> apiResponse = new ApiResponse<List<Goal>>(goalsList);
list.setValue(apiResponse);
}
}
});
} else {
Throwable error = new Throwable("No user logged in");
ApiResponse<List<Goal>> apiResponse = new ApiResponse<List<Goal>>(error);
list.setValue(apiResponse);
return list;
}
return list;
}
Following my debug log comparison between .getData and .toObject:
12-05 19:53:42.663 11470-11470/com.benjaminsommer.dailygoals D/firebaseService: DocumentSnapshop.getData: {goals={goalRewardType=true, remoteId=10L44s0EcvTTzGajzhidgoals, id=2, goalFrequencyCode=1001111111, activated=1, goalColor=-4365347, goalCategory=8, goalDescription=Description Test, goalReward=1, goalPos=1, goalFrequency=2, goalName=Test}}
12-05 19:53:42.663 11470-11470/com.benjaminsommer.dailygoals D/firebaseService: DocumentSnapshot.toObject(Goal.class): Goal{id=0, remoteId='', goalPos=0, goalName='', goalCategory=15, goalDescription='', goalColor=2131558437, goalFrequency=0, goalFrequencyCode=1111111111, goalRewardType=false, goalReward=0.0, activated=1, isSynced=false}
.toObject doesn't transform the datasnapshot to my class. I already checked the documentation:
Important: Each custom class must have a public constructor that takes
no arguments. In addition, the class must include a public getter for
each property.
I have a constructor with no args and public getters for each property. I tried it with an empty constructor, but not working either. Is anything wrong with my getters? I use it in combination with Room, maybe there can be an issue?
Really appreciate your help and support.
Thanks, Ben

Related

How do you cloud save each level data. for unity Game Like Candy crush game

I am developing a puzzle game for Android using unity. So I want to save the score, time and stars earned for each level in the google play Cloud. But I am able to save it for one single level if I try to save it for more then 1 level. it overwrites the previous data. So how do I overcome this problem?
public class CloudSave : MonoBehaviour {
[SerializeField]
private Text message;
private int totalCoin = 20;
public int levelNumber;
public int starEarnedPerLevel;
#region Cloud_Save
private string GetSaveString() {
string data = "";
data += PlayerPrefs.GetInt("HighScore").ToString();
data += "|";
data += totalCoin.ToString();
data += "|";
data += levelNumber.ToString();
data += "|";
data += starEarnedPerLevel.ToString();
return data;
}
private void LoadSaveString(string save) {
string[] data = save.Split('|');
PlayerPrefs.SetInt("HighScore", int.Parse(data[0]));
totalCoin = int.Parse(data[1]);
levelNumber = int.Parse(data[2]);
starEarnedPerLevel = int.Parse(data[3]);
Debug.Log("LoadSaveString Function");
}
private bool isSaving = false;
public void OpenSave(bool saving) {
Debug.Log("Open Save");
if (Social.localUser.authenticated) {
isSaving = saving;
((PlayGamesPlatform)Social.Active).SavedGame
.OpenWithAutomaticConflictResolution(
"MyCloudFile",
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime, SavedGameOpen);
}
}
private void SavedGameOpen(SavedGameRequestStatus reqStatus, ISavedGameMetadata metadata) {
Debug.Log("SavedGameOpen");
if (reqStatus == SavedGameRequestStatus.Success) {
if (isSaving)// Writting
{
byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(GetSaveString());
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().WithUpdatedDescription("Saved At :" + System.DateTime.Now.ToString()).Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(metadata, update, data, SaveUpdate);
}
else // Reading or Loading
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(metadata,SaveRead);
}
}
}
//success Save
private void SaveUpdate(SavedGameRequestStatus reqStatus, ISavedGameMetadata metadata) {
Debug.Log(reqStatus);
if (reqStatus == SavedGameRequestStatus.Success)
{
message.text = ("Data Saved successfully ");
}
else {
message.text = ("Data Saved failed " + reqStatus.ToString());
}
}
//Load
private void SaveRead(SavedGameRequestStatus reqStatus, byte[] data) {
if (reqStatus == SavedGameRequestStatus.Success) {
string savedData = System.Text.ASCIIEncoding.ASCII.GetString(data);
message.text = ("Data read successfully " + savedData);
LoadSaveString(savedData);
}
else
{
message.text = ("Data read Failed!" + reqStatus.ToString());
}
}
#endregion
}
Use JSON to keep the game data , splitting string is hard to maintain.
{
"currentLevel":"3",
"totalCoin":"20",
"levelData":[
{
"levelNum":1,
"starEarn":3,
"highScore":123456
},
{
"levelNum":2,
"starEarn":1,
"highScore":1234
}
]
}
//GameData.cs
[System.Serializable]
public class GameData {
public int currentLevel;
public int totalCoin;
private Dictionary<int, LevelData> levelDataList;
public GameData(){
//
// constructor
//
}
public string GetSaveString(){
string res = JsonUtility.ToJson (this);
res = res.Substring (0, res.Length - 1);
res = res + ",\"levelData\":[";
foreach (LevelData levelData in levelDataList.Values) {
res = res + JsonUtility.ToJson (levelData);
res = res + ",";
}
if(levelDataList.Count > 0)
res = res.Substring (0, res.Length - 1);
res = res + "]}";
return res;
}
}
//LevelData.cs
[System.Serializable]
public class LevelData {
public int levelNum;
public int starEarn;
public int highScore;
public LevelData(){
//
// constructor
//
}
}

How to speed up data loading into recyclerview?

I'm in a dire situation of finding a solution for speeding up loading data into the RecyclerView. Data load from the server database and populate the row. Each row has a few EditTexts where user enters some values. Within the OnBindViewHolder, each value entered by the user is captured using a text watcher, and then totals are calculated and displayed real-time in the footer of the parent view.(outside the RecyclerView) Also, inside the OnBindViewHolder, a method is called to update a table in the DB, with the values just entered and captured.
So, basically, when each row gets bound, both the DB and the UI get updated. When the data load is huge, loading of the recyclerView is really slow. What I have tried are moving the DB update to a separate thread, using async task to update the DB. But nothing worked. What should I do here?
Adapter's OnBindViewHolder code is displayed below.
public void onBindViewHolder(final MyViewHolder holder, #SuppressLint("RecyclerView") final int position, List<Object> payload) {
//onBindViewHolder(holder,position);
holder.ref = position;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
onBind = true;
// data passed from getAllData method aka all from TempInvoice
SalesInvoiceModel siModel = salesInvoice.get(position);
holder.code.setText(siModel.getCode());
holder.product.setText(siModel.getProduct());
holder.batchNum.setText(siModel.getBatchNumber());
try {
Date date = simpleDateFormat.parse(siModel.getExpiryDate());
holder.expiry.setText(date.toString());
} catch (Exception ex) {
holder.expiry.setText("Error");
}
holder.expiry.setText(siModel.getExpiryDate());
if (siModel.getDiscountRate() > 0) {
holder.unitprice.setText(siModel.getRetailPrice() + "");
} else {
holder.unitprice.setText(siModel.getUnitPrice() + "");
}
holder.stock.setText(siModel.getStock() + "");
holder.lineval.setText(siModel.getLineValue() + "");
if (payload == null || payload.size() == 0) {
holder.shelf.setText(siModel.getShelf() + "");
holder.request.setText(siModel.getRequest() + "");
holder.order.setText(siModel.getOrder() + "");
holder.free.setText(siModel.getFree() + "");
holder.discount.setText(siModel.getDiscountRate() + "");
} else {
for (Object editText : payload) {
//String val = (String)payload.get(0);
String val = (String) editText;
switch (val) {
case SHELF:
if (lostFocus) {
holder.shelf.setText(salesInvoice.get(position).getShelf() + "");
}
break;
case REQUEST:
if (lostFocus) {
holder.request.setText(salesInvoice.get(position).getRequest() + "");
}
break;
case ORDER:
if (lostFocus) {
holder.order.setText(salesInvoice.get(position).getOrder() + "");
}
break;
case FREE:
if (lostFocus) {
holder.free.setText(salesInvoice.get(position).getFree() + "");
}
break;
case DISCOUNT:
if (lostFocus) {
holder.discount.setText(salesInvoice.get(position).getDiscountRate() + "");
}
break;
case LINEVAL:
holder.lineval.setText(salesInvoice.get(position).getLineValue() + "");
break;
default:
onBindViewHolder(holder, position);
break;
}
}
}
//ADD TEXT WATCHERS
holder.shelf.setOnFocusChangeListener(new FocusChangeListener());
holder.shelf.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
int pos = holder.ref;
if (!onBind) {
if (!s.equals("")) {
notifyItemChanged(pos, SHELF);
Log.d(TAG, "inside text change typed shelf_" + s);
salesInvoice.get(pos).setShelf(Integer.parseInt(s + ""));
} else {
salesInvoice.get(pos).setShelf(0);
}
lastUpdatedRow = pos;
}
}
});
holder.request.setOnFocusChangeListener(new FocusChangeListener());
holder.request.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valHasChanged = false;
boolean freeHasChanged = false;
int pos = holder.ref;
if (!onBind) {
if (!(s.equals(""))) {
int val = Integer.parseInt((s));
int stock = salesInvoice.get(pos).getStock();
// if stock does not have the particular product
if (val > stock) {
val = stock;
valHasChanged = true;
}
salesInvoice.get(pos).setRequest(val);
if (!refresh) salesInvoice.get(pos).setOrder(val);
if (salesInvoice.get(pos).getFree() + salesInvoice.get(pos).getOrder() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
freeHasChanged = true;
}
} else {
salesInvoice.get(pos).setRequest(0);
}
notifyItemChanged(pos, ORDER);
if (valHasChanged) {
notifyItemChanged(pos, REQUEST);
}
if (freeHasChanged) {
notifyItemChanged(pos, FREE);
}
lastUpdatedRow = pos;
}
}
});
holder.order.setOnFocusChangeListener(new FocusChangeListener());
holder.order.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valHasChanged = false;
boolean freeHasChanged = false;
int pos = holder.ref;
if (!onBind) {
if (!(s.equals(""))) {
int val = Integer.parseInt(s);
int stock = salesInvoice.get(pos).getStock();
if (val > stock) {
val = stock;
valHasChanged = true;
}
salesInvoice.get(pos).setOrder(val);//make sure we set returnQty before
//checking the total of returnQty and free against stock
if (salesInvoice.get(pos).getOrder() + salesInvoice.get(pos).getFree() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
freeHasChanged = true;
}
} else {
salesInvoice.get(pos).setOrder(0);
}
if (valHasChanged) {
notifyItemChanged(pos, ORDER);//notify the adapter that value changed and refresh the view mentioned by the string
}
if (freeHasChanged) notifyItemChanged(pos, FREE);
notifyItemChanged(pos, LINEVAL);
lastUpdatedRow = pos;
}
}
});
holder.free.setOnFocusChangeListener(new FocusChangeListener());
holder.free.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
boolean valChanged = false;
int pos = holder.ref;
if (!onBind) {
if ((!s.equals("")) && (!(s.equals("0")))) {
int val = Integer.parseInt(s);
salesInvoice.get(pos).setFree(val);
holder.discount.setEnabled(false);
if (salesInvoice.get(pos).getOrder() + salesInvoice.get(pos).getFree() > salesInvoice.get(pos).getStock()) {
salesInvoice.get(pos).setFree(0);
valChanged = true;
holder.discount.setEnabled(true);
}
} else {
salesInvoice.get(pos).setFree(0);
holder.discount.setEnabled(true);
}
notifyItemChanged(pos, LINEVAL);
if (valChanged) notifyItemChanged(pos, FREE);
holder.setCursor(FREE);
lastUpdatedRow = pos;
}
}
});
holder.discount.setOnFocusChangeListener(new FocusChangeListener());
holder.discount.addTextChangedListener(new GenericTextWatcher() {
#Override
public void afterTextChanged(String s) {
int pos = holder.ref;
if (!(s.equals(salesInvoice.get(pos).getDiscountRate() + ""))) {
if ((!s.equals("")) && (!(s.equals("0"))) && (!(s.equals("0.0"))) && (!(s.equals("0.")))) {
Double rate = Double.parseDouble(s.toString().trim());
Log.i(" RAte ", rate + "");
salesInvoice.get(pos).setDiscountRate(rate);
holder.free.setEnabled(false);
} else {
salesInvoice.get(pos).setDiscountRate(0.0);
holder.free.setEnabled(true);
}
if (!onBind) {
notifyItemChanged(pos, LINEVAL);
lastUpdatedRow = pos;
}
}
}
});
if (position % 2 == 0) {
holder.setColor(Color.LTGRAY);
} else {
holder.setColor(Color.GRAY);
}
onBind = false;
notifyUpdate(); //calling to update the UI
Log.d("ASY", "before db call");
DBAdapterAsync dbAdapter = new DBAdapterAsync(getContextForAdapter);
dbAdapter.execute(salesInvoice.get(holder.ref));
Log.d("ASY", "after db call");
}
//async task class for DB Update
#SuppressLint("StaticFieldLeak")
private class DBAdapterAsync extends AsyncTask<SalesInvoiceModel, Void, String> {
private SQLiteDatabase db;
private DBHelper dbHelper;
DBAdapterAsync(Context context) {
this.dbHelper = new DBHelper(context);
Log.d("ASY", "inside constructor");
}
#Override
protected void onPreExecute() {
try {
db = dbHelper.getWritableDatabase();
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
dbHelper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(SalesInvoiceModel... models) {
SalesInvoiceModel model = models[0];
Log.d(TAG, "inside updateInvoiceData_");
Log.d(TAG, "shelf_" + model.getShelf());
Log.d(TAG, "order_" + model.getOrder());
Log.d(TAG, "free_" + model.getFree());
String sql = "UPDATE temp_invoice SET" +
" Shelf=" + model.getShelf() + " , Request=" + model.getRequest()
+ " , OrderQty=" + model.getOrder() + " , Free=" + model.getFree()
+ " , Disc=" + model.getDiscountRate() + " , LineVal=" + model.getLineValue()
+ ", RetailPriceLineVal=" + model.getRetailLineVal()
+ " WHERE _id=" + model.getId();
db.execSQL(sql);
Log.d(TAG, "DB method finished,");
Log.d("ASY", "after do in background");
return null;
}
}

IndexOutOfRangeException: Array index is out of range. DataCache.GetAchievementCacheData () (at Assets/Scripts/Mission/Plugin/DataCache.cs:329)

When I run the game using unity I get this error continuously in the console window and the loading screen is not going further next. Help me to fix this issue.
IndexOutOfRangeException: Array index is out of range.
DataCache.GetAchievementCacheData () (at
Assets/Scripts/Mission/Plugin/DataCache.cs:329)
Here is my code below
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using UnityEngine;
//Class luu mission current
public class CurrentMission
{
public string FB_id { get; set; }
public string Name { get; set; }
public string Mission { get; set; }
public CurrentMission(string id, string name, string mission)
{
this.FB_id = id;
this.Name = name;
this.Mission = mission;
}
public CurrentMission()
{
this.FB_id = "";
this.Name = "";
this.Mission = "";
}
}
public class MissionDataSave
{
public int Mission;
public long Score;
public int Star;
public int Open;//0-false. 1-true
public MissionDataSave(int mission, long score, int star, int open)
{
Mission = mission;
Score = score;
Star = star;
Open = open;
}
public MissionDataSave()
{
Mission = 0;
Score = 0;
Star = 0;
Open = 0;
}
}
public class AchievementCache
{
//group nhiem vu
public int Group;
//Level hien tai cua group
public int Level;
//Gia tri hien tai
public int Value;
//Thong bao mission hoan thanh
public int Notify;//0 - False, 1 - true
//public AchievementCache()
//{
// this.Group = 1;
// this.Level = 1;
// this.Value = 0;
//}
public AchievementCache(int group, int level, int value, int notify)
{
this.Group = group;
this.Value = value;
this.Level = level;
this.Notify = notify;
}
public AchievementCache()
{
this.Group = 1;
this.Value = 0;
this.Level = 1;
this.Notify = 0;
}
}
public class DataCache
{
public static string FB_ID = "FB_ID";
public static string FB_USER = "FB_USER";
public static string Achievement_data_key = "Achievement_data_key";
public static string Mission_data_key = "Mission_data_key";
public static string Current_mission_data_key = "Current_mission_data_key";
public static AchievementCache[] dataAchievementCache;
public static MissionDataSave[] dataMissionCache;
public static CurrentMission[] dataCurrentMissionCache;
//public static string XML_Current_Mission_Path = "CurrentMissionSave.xml";
//public static string XML_Data_Mission_Path = "DataMissionSave.xml";
//public static string XML_Data_Achievement_Path = "AchievementCache.xml";
//serialize xml theo tung phan tu
//public static List<MissionDataSave> DeserializeMissionDataSaveListFromXML(string filePath)
//{
// if (!System.IO.File.Exists(filePath))
// {
// Debug.LogError("File " + filePath + " not exist!");
// return new List<MissionDataSave>();
// }
// XmlSerializer deserializer = new XmlSerializer(typeof(List<MissionDataSave>), new XmlRootAttribute("MissionDataSaveRoot"));
// TextReader textReader = new StreamReader(filePath);
// List<MissionDataSave> movies = (List<MissionDataSave>)deserializer.Deserialize(textReader);
// textReader.Close();
// return movies;
//}
//public static void readXMLTest()
//{
// string xmlDataCache1 = Application.persistentDataPath + "/" + XML_Current_Mission_Path;
// TextReader textReader = new StreamReader(xmlDataCache1);
// XmlDocument xmlDoc = new XmlDocument();
// xmlDoc.Load(textReader);
// XmlNodeList xmlNodeList = xmlDoc.DocumentElement.ChildNodes;
// Debug.Log("TRUOC");
// foreach (XmlNode node in xmlNodeList)
// {
// Debug.Log("aaaaaaaaaaaaaaaaaaaaa " + node.Attributes["Id"].Value);
// }
// Debug.Log("SAU");
// XmlNode root = xmlDoc.DocumentElement;
// XmlElement elem = xmlDoc.CreateElement("CurrentMissionCache");
// elem.SetAttribute("Id", "112312");
// elem.SetAttribute("Name", "NameDG");
// elem.SetAttribute("Mission", "MissionDG");
// root.AppendChild(elem);
// textReader.Close();
// xmlDoc.Save(xmlDataCache1);
//}
//Add mission xml node
public static void UpdateMissionScore(long score, int star, int mission, int open)
{
MissionDataSave data = dataMissionCache[mission - 1];
if (data.Star < star)
{
data.Star = star;
}
if (data.Score < score)
{
data.Score = score;
}
data.Open = open;
}
public static void SaveMissionDataCache(bool submitToServer = false)
{
string dataSave = "";
string dataSendServer = "";
for (int i = 0; i < dataMissionCache.Length; i++)
{
dataSave += dataMissionCache[i].Mission + "-" + dataMissionCache[i].Score + "-" + dataMissionCache[i].Star + "-" + dataMissionCache[i].Open + ",";
//Chi gui nhung mission da open len server
if (dataMissionCache[i].Open == 1)
{
if (dataSendServer.Length > 0)
dataSendServer += ",";
dataSendServer += dataMissionCache[i].Mission + "-" + dataMissionCache[i].Score + "-" + dataMissionCache[i].Star + "-" + dataMissionCache[i].Open;
}
}
Debug.Log("Data save " + dataSave);
PlayerPrefs.SetString(Mission_data_key, dataSave);
if (submitToServer)
{
Debug.Log("Data send server " + dataSendServer);
AudioControl.getMonoBehaviour().StartCoroutine(DHS.PostMeInfoMissionUpdate(FB.UserId, dataSendServer));
}
}
public static void GetMissionDataCache()
{
int max_mission = 100;
if (dataMissionCache != null)
{
dataMissionCache = null;
}
dataMissionCache = new MissionDataSave[max_mission];
//Tao moi neu chua co
if (!PlayerPrefs.HasKey(Mission_data_key))
{
string datas = "1-0-0-1,";
for (int i = 2; i <= max_mission; i++)
{
//Mission - Score - Star - Open
if (DataMissionControlNew.test)
{
datas += i + "-0-0-1,";
//if (i < 16)
// datas += i + "-0-0-1,";
//else datas += i + "-0-0-0,";
}
else
{
datas += i + "-0-0-0,";
}
}
PlayerPrefs.SetString(Mission_data_key, datas);
}
string missionData = PlayerPrefs.GetString(Mission_data_key);
string[] data = missionData.Split(',');
for (int i = 0; i < max_mission; i++)
{
string[] infoData = data[i].Split('-');
//Debug.Log("Info " + data[i]);
string mission = infoData[0];
string score = infoData[1];
string star = infoData[2];
string open = infoData[3];
dataMissionCache[i] = new MissionDataSave(Convert.ToUInt16(mission), Convert.ToUInt32(score), Convert.ToUInt16(star), Convert.ToUInt16(open));
}
}
//-------------------------CURRENT MISSION---------------------------
//Add current mission xml node
public static void SaveCurrentMission(string data = "")
{
if (String.IsNullOrEmpty(data))
{
string dataSave = "";
for (int i = 0; i < dataCurrentMissionCache.Length; i++)
{
if (dataSave.Length > 0)
dataSave += ",";
dataSave += dataCurrentMissionCache[i].FB_id + "-" + dataCurrentMissionCache[i].Name + "-" + dataCurrentMissionCache[i].Mission;
}
PlayerPrefs.SetString(Current_mission_data_key, dataSave);
}
else
{
PlayerPrefs.SetString(Current_mission_data_key, data);
GetCurrentMission();
}
}
public static void GetCurrentMission()
{
if (!PlayerPrefs.HasKey(Current_mission_data_key))
{
PlayerPrefs.SetString(Current_mission_data_key, "Me-User-1");
}
if (dataCurrentMissionCache != null)
{
dataCurrentMissionCache = null;
}
string current_data = PlayerPrefs.GetString(Current_mission_data_key);
string[] data = current_data.Split(',');
dataCurrentMissionCache = new CurrentMission[data.Length];
for (int i = 0; i < data.Length; i++)
{
string[] info = data[i].Split('-');
//fb - User name - missison
dataCurrentMissionCache[i] = new CurrentMission(info[0], info[1], info[2]);
}
}
public static void SetMeCurrentMission(int mission)
{
for (int i = 0; i < DataCache.dataCurrentMissionCache.Length; i++)
{
if ("Me".Equals(DataCache.dataCurrentMissionCache[i].FB_id))
{
int old = Convert.ToInt16(DataCache.dataCurrentMissionCache[i].Mission);
if (old < mission)
{
DataCache.dataCurrentMissionCache[i].Mission = "" + mission;
DataCache.UpdateMissionScore(0, 0, mission, 1);//Them mission moi vao xml
}
}
}
DataCache.SaveCurrentMission();
}
//-------------------------ACHIEVEMENT---------------------------
//Ghi de len du lieu cu
public static void ReplaceAchievementCache(int groupLevel, int value, int level = -1)
{
dataAchievementCache[groupLevel - 1].Value = value;
if (level != -1)
{
dataAchievementCache[groupLevel - 1].Level = level;
}
}
//Cap nhat them du lieu
public static void AddAchievementCache(int groupLevel, int addValue, int addLevel = 0)
{
dataAchievementCache[groupLevel - 1].Level += addLevel;
dataAchievementCache[groupLevel - 1].Value += addValue;
}
public static void GetAchievementCacheData()
{
Debug.Log("-------------GetAchievementCacheData--------------------");
if (dataAchievementCache != null)
{
dataAchievementCache = null;
}
dataAchievementCache = new AchievementCache[22];
//Tao achievement
if (!PlayerPrefs.HasKey(Achievement_data_key))
{
string achi = "";
for (int i = 1; i <= 22; i++)
{
achi += i + "-1-0-0,";
}
//Debug.Log("Create new achievement " + achi);
PlayerPrefs.SetString(Achievement_data_key, achi);
}
string achievement = PlayerPrefs.GetString(Achievement_data_key);
//Debug.Log(achievement);
string[] achie = achievement.Split(',');
for (int i = 0; i< dataAchievementCache.Length; i++)
{
//Debug.Log(achie[i]);
string[] infoAchie = achie[i].Split('-');
string group = infoAchie[0];
string level = infoAchie[1];
string value = infoAchie[2];
string notify = infoAchie[3];
//Debug.Log(group +" " + dataAchievementCache[i].Group);
dataAchievementCache[i] = new AchievementCache();
dataAchievementCache[i].Group = Convert.ToInt16(group);
dataAchievementCache[i].Level = Convert.ToInt16(level);
dataAchievementCache[i].Value = Convert.ToInt32(value);
dataAchievementCache[i].Notify = Convert.ToInt16(notify);
}
}
public static void SaveAchievementCache(bool sendServer = false)
{
try
{
Debug.Log("-------------------SaveAchievementCache-----------------");
if (dataAchievementCache != null)
{
string achievement = "";
for (int i = 0; i < dataAchievementCache.Length; i++)
{
string s = "" + dataAchievementCache[i].Group + "-" + dataAchievementCache[i].Level + "-" + dataAchievementCache[i].Value + "-" + dataAchievementCache[i].Notify + ",";
achievement += s;
}
//Debug.Log("----------LUU ACHIEVEMENT------------ " + achievement);
PlayerPrefs.SetString(Achievement_data_key, achievement);
if (FB.IsLoggedIn && sendServer)
{
//Nếu chưa có playerprefs thì sẽ submit lên luôn
//Nếu có rồi thì phải check nó cập nhật hoàn thành từ server về thì mới cho up lên
bool check = !PlayerPrefs.HasKey(DataMissionControlNew.key_update_achievement_data_from_server) ||
(PlayerPrefs.HasKey(DataMissionControlNew.key_update_achievement_data_from_server) && PlayerPrefs.GetInt(DataMissionControlNew.key_update_achievement_data_from_server) == 1);
if (check)
{
AudioControl.getMonoBehaviour().StartCoroutine(DHS.PostMeInfoUpdate(DFB.UserId, "" + VariableSystem.diamond, "" + achievement, "", (www) =>
{
Debug.Log("----------Update achievement to server success!------------- " + achievement);
}));
}
else
{
Debug.Log("----------KHONG CHO UP ACHIEVEMENT VA DIAMOND LEN SERVER------------- " + PlayerPrefs.GetInt(DataMissionControlNew.key_update_mission_data_from_server, 0));
}
}
}
}
catch (Exception e)
{
Debug.Log("------------ERROR ---------------" + e.Message);
if (DataMissionControlNew.test)
{
MobilePlugin.getInstance().ShowToast("ERROR " + e.Message);
}
}
}
public static void DeleteUserData()
{
PlayerPrefs.DeleteKey(FB_ID);
PlayerPrefs.DeleteKey(Mission_data_key);
PlayerPrefs.DeleteKey(Current_mission_data_key);
PlayerPrefs.DeleteKey(Achievement_data_key);
PlayerPrefs.DeleteKey("diamond");
PlayerPrefs.DeleteKey(DataMissionControlNew.key_update_mission_data_from_server);
VariableSystem.diamond = 8;
VariableSystem.heart = 5;
}
public static void RestoreUserData(int diamond, string achievement)
{
Debug.Log("Restore user data");
VariableSystem.diamond = diamond;
VariableSystem.heart = PlayerPrefs.GetInt("heart", 5);
string[] achie = achievement.Split(',');
if (achie.Length > 5)
{
for (int i = 0; i < dataAchievementCache.Length; i++)
{
string[] infoAchie = achie[i].Split('-');
string group = infoAchie[0];
string level = infoAchie[1];
string value = infoAchie[2];
string notify = infoAchie[3];
dataAchievementCache[i].Group = Convert.ToInt16(group);
dataAchievementCache[i].Level = Convert.ToInt16(level);
dataAchievementCache[i].Value = Convert.ToInt32(value);
dataAchievementCache[i].Notify = Convert.ToInt16(notify);
}
//Debug.Log("---Luu achievement----");
SaveAchievementCache();
GetAchievementCacheData();
}
Debug.Log("----------------ACHIEVEMENT da dc cap nhat tu -----------------");
PlayerPrefs.SetInt(DataMissionControlNew.key_update_achievement_data_from_server, 1);
}
The line 329 is this
string level = infoAchie[1];
The problem is coming from the last comma you are adding in the string you are adding to your PlayerPrefs in this part:
if (!PlayerPrefs.HasKey(Achievement_data_key))
{
string achi = "";
for (int i = 1; i <= 22; i++)
{
achi += i + "-1-0-0,";
}
//Debug.Log("Create new achievement " + achi);
PlayerPrefs.SetString(Achievement_data_key, achi);
}
This code generates this string:
1-1-0-0,2-1-0-0,3-1-0-0,4-1-0-0,5-1-0-0,6-1-0-0,7-1-0-0,8-1-0-0,9-1-0-0,10-1-0-0,11-1-0-0,12-1-0-0,13-1-0-0,14-1-0-0,15-1-0-0,16-1-0-0,17-1-0-0,18-1-0-0,19-1-0-0,20-1-0-0,21-1-0-0,22-1-0-0,
Keep in memory that last comma at the end of the string.
You are later doing a split on the ',' character, and iterating over them.
string[] achie = achievement.Split(',');
for (int i = 0; i< dataAchievementCache.Length; i++)
{
//Debug.Log(achie[i]);
string[] infoAchie = achie[i].Split('-');
string group = infoAchie[0];
string level = infoAchie[1];
...
}
The problem is that by doing so, your achie string array contains an empty last element. So when you are later splitting on the "-" character, your infoAchie string array only contains one element: the empty string. The first line:
string group = infoAchie[0];
Still works, but is filled with the empty string. Then:
string level = infoAchie[1];
Can't work, as you are indeed out of the bounds of the infoAchie array.
The solution would be to add the comma to your string only if it is not the last element.
Also, I strongly advise you to use a StringBuilder over a simple string for optimization purposes. Your code could then look like, for instance:
if (!PlayerPrefs.HasKey(Achievement_data_key))
{
StringBuilder achi = new StringBuilder();
for (int i = 1; i <= 22; i++)
{
achi.Append(i).Append("-1-0-0");
if(i != 22)
achi.Append(",");
}
//Debug.Log("Create new achievement " + achi);
PlayerPrefs.SetString(Achievement_data_key, achi.ToString());
}
Which generates this string:
1-1-0-0,2-1-0-0,3-1-0-0,4-1-0-0,5-1-0-0,6-1-0-0,7-1-0-0,8-1-0-0,9-1-0-0,10-1-0-0,11-1-0-0,12-1-0-0,13-1-0-0,14-1-0-0,15-1-0-0,16-1-0-0,17-1-0-0,18-1-0-0,19-1-0-0,20-1-0-0,21-1-0-0,22-1-0-0

Display list of time zones similar to that of timezones displayed in S Planner app

Is there a way in which I can display the list of Time zones in a format like (GMT+1.00) Windhoek like the way we see in S Planner on the Android app?
Can anyone help me in sorting out this issue?
Thanks in adavance
First I suggest you to create a wrapper class to manage the format of TimeZone objects as follow:
public class TimeZoneWrapper {
private final TimeZone timeZone;
private String timeZoneID;
private String timeZoneDisplay;
private String timeZoneRawDisplayName;
public TimeZoneWrapper(final TimeZone timeZone) {
this.timeZone = timeZone;
setDisplayStrings();
}
private void setDisplayStrings() {
this.timeZoneID = timeZone.getID().replaceAll("_", " ");
int offset = timeZone.getRawOffset();
if (timeZone.inDaylightTime(new Date())) {
offset = offset + timeZone.getDSTSavings();
}
this.timeZoneRawDisplayName = timeZone.getDisplayName(false,
TimeZone.SHORT);
final int offsetHrs = offset / 1000 / 60 / 60;
final int offsetMins = offset / 1000 / 60 % 60;
if (offsetHrs + offsetMins == 0) {
this.timeZoneDisplay = "GMT";
} else {
String suffix = "";
if (offset < 0) {
suffix += "-";
} else {
suffix += "+";
}
if (offsetMins != 0) {
suffix += offsetHrs + "." + offsetMins;
} else {
suffix += offsetHrs;
}
this.timeZoneDisplay = "GMT" + suffix;
}
}
public String getTimeZoneID() {
return timeZoneID;
}
public String getTimeZoneDisplay() {
return timeZoneDisplay;
}
public String getTimeZoneRawDisplayName() {
return timeZoneRawDisplayName;
}
public TimeZone getTimeZone() {
return timeZone;
}
#Override
public final boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TimeZoneWrapper)) {
return false;
}
final TimeZoneWrapper that = (TimeZoneWrapper) o;
return that.timeZone.equals(this.timeZone);
}
}
Once you have created (if you want) this wrapper class you can retrieve the TimeZones from your device with the following method in your mainActivity.
private List<TimeZoneWrapper> buildTimeZoneWrappers() {
final List<TimeZoneWrapper> timeZoneWrappers = new ArrayList<TimeZoneWrapper>();
final List<TimeZone> timeZones = new ArrayList<TimeZone>();
final String[] timeZoneIds = TimeZone.getAvailableIDs();
for (final String id : timeZoneIds) {
timeZones.add(TimeZone.getTimeZone(id));
}
for (final TimeZone timeZone : timeZones) {
timeZoneWrappers.add(new TimeZoneWrapper(timeZone));
}
return timeZoneWrappers;
}
Now you have a list of "well" formatted timezone, so if you need a picker with this value you simply have to create one with them.
String[] temp;
for (int i=0;i<timeZoneWrappers.size();i++){
temp[i]=timeZoneWrappers.get(i).getTimeZoneDisplay();
}
NumberPicker picker = new NumberPicker(getApplicationContext());
picker.setDisplayedValues(temp);
Let me know;)

Android Parcelable and inheritance

I have a class Drills and few classes that extend it, for example AddDrill.
I want to be able to pass this Drill objects "family" between activities, so I am using Parcelable.
I have found this answer and this example and I have created this Drill and AddDrill classes, I think I have done something wrong, is every thing good in my implementation?
Drill:
package com.simplemathgame;
import android.os.Parcel;
import android.os.Parcelable;
public abstract class Drill implements Parcelable{
protected int firstNumber;
protected int secondNumber;
protected int answer;
protected int userAnswer;
protected String userAnswerString;
protected String symbol;
protected int minBound, maxBound;
protected int drillNumber;
public String getUserAnswerString() {
return userAnswerString;
}
public void setUserAnswerString(String userAnswerString) {
this.userAnswerString = userAnswerString;
}
Drill(int min, int max){
minBound = min;
maxBound = max;
answer = answerCalculatetion();
userAnswerString = "";
}
public Drill(Parcel in) {
readFromParcel(in);
}
public int getDrillNumber() {
return drillNumber;
}
public void setDrillNumber(int drillNumber) {
this.drillNumber = drillNumber;
}
public int getUserAnswer() {
return userAnswer;
}
public void setUserAnswer(int userAnswer) {
this.userAnswer = userAnswer;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public int getMinBound() {
return minBound;
}
public void setMinBound(int minBound) {
this.minBound = minBound;
}
public int getMaxBound() {
return maxBound;
}
public void setMaxBound(int maxBound) {
this.maxBound = maxBound;
}
//getters and setters
public int getFirstNumber() {
return firstNumber;
}
public void setFirstNumber(int firstNumber) {
this.firstNumber = firstNumber;
}
public int getSecondNumber() {
return secondNumber;
}
public void setSecondNumber(int secondNumber) {
this.secondNumber = secondNumber;
}
public int getAnswer() {
return answer;
}
public void setAnswer(int answer) {
this.answer = answer;
}
protected int getRandomNumber(int high, int low){
return (int) ((Math.random( ) * (high - low + 1)) + low);
}
protected abstract int answerCalculatetion();
protected String printDrill(){
String FirstNumberS;
String SecondNumberS;
if(this.getFirstNumber() < 0){
FirstNumberS = "(" + this.getFirstNumber() + ")";
}
else{
FirstNumberS = "" + this.getFirstNumber();
}
if(this.getSecondNumber() < 0){
SecondNumberS = "(" + this.getSecondNumber() + ")";
}
else{
SecondNumberS = "" + this.getSecondNumber();
}
return (FirstNumberS + " " + this.getSymbol() + " " + SecondNumberS + " " + "=");
}
protected String printDrillAnswer(){
String FirstNumberS;
String SecondNumberS;
String answerS;
if(this.getAnswer() < 0){
answerS = "(" + this.getAnswer() + ")";
}
else{
answerS = "" + this.getAnswer();
}
if(this.getFirstNumber() < 0){
FirstNumberS = "(" + this.getFirstNumber() + ")";
}
else{
FirstNumberS = "" + this.getFirstNumber();
}
if(this.getSecondNumber() < 0){
SecondNumberS = "(" + this.getSecondNumber() + ")";
}
else{
SecondNumberS = "" + this.getSecondNumber();
}
return (FirstNumberS + " " + this.getSymbol() + " " + SecondNumberS + " " + "=" + " " + answerS);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// We just need to write each field into the
// parcel. When we read from parcel, they
// will come back in the same order
dest.writeInt(firstNumber);
dest.writeInt(secondNumber);
dest.writeInt(answer);
dest.writeInt(userAnswer);
dest.writeString(userAnswerString);
dest.writeString(symbol);
dest.writeInt(minBound);
dest.writeInt(maxBound);
dest.writeInt(drillNumber);
}
/**
*
* Called from the constructor to create this
* object from a parcel.
*
* #param in parcel from which to re-create object
*/
protected void readFromParcel(Parcel in) {
// We just need to read back each
// field in the order that it was
// written to the parcel
firstNumber = in.readInt();
secondNumber = in.readInt();
answer = in.readInt();
userAnswer = in.readInt();
userAnswerString = in.readString();
symbol = in.readString();
minBound = in.readInt();
maxBound = in.readInt();
}
}
AddDrill:
package com.simplemathgame;
import android.os.Parcel;
import android.os.Parcelable;
public class AddDrill extends Drill {
AddDrill(int min, int max) {
super(min, max);
symbol = "+";
firstNumber = getRandomNumber(min, max);
secondNumber = getRandomNumber(min, max);
answer = answerCalculatetion();
}
private AddDrill(Parcel in) {
super(in);
}
protected int answerCalculatetion() {
return (this.getFirstNumber() + this.getSecondNumber());
}
public static final Parcelable.Creator<AddDrill> CREATOR = new Parcelable.Creator<AddDrill>() {
public AddDrill createFromParcel(Parcel in) {
return new AddDrill(in);
}
public AddDrill[] newArray(int size) {
return new AddDrill[size];
}
};
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
}
Thanks
In your AddDrill class, you'll need to implement writeToParcel() method and also the constructor from a Parcel. You'll probably need to use #Override for both of such methods as well but you need to experiment to find out the final solution

Categories

Resources