I am having a problem incrementing my integer variable after a certain condition is met in Android Programming. Why is it not incrementing?
The code below are implemented on an ImageButton which lies a class (Activity) called Product.
int count = 1;
List<Item> prod = ShoppingCart.getInstance().getProducts();
// if arraylist is null --> add a product
if(prod != null && prod.isEmpty()){
ShoppingCart.getInstance().addItem(new Item(
namePureString,
manufacturePureString,
pricePureString,
"",
count
));
Toast.makeText(getApplicationContext(), namePureString + " Added To Cart", Toast.LENGTH_SHORT).show();
}else {
for (Item products : ShoppingCart.getInstance().myProducts) {
// here i am checking if the product exists, if it does --> count has to increment
if (products.getManufacture().equals(manufacturePureString)) {
count += count;
Toast.makeText(getApplicationContext(), "You Added This Product\nQuantity Will Increase",
Toast.LENGTH_SHORT).show();
ShoppingCart.getInstance().setItemExists(new Item(
namePureString,
manufacturePureString,
pricePureString,
"",
count
));
} else {
ShoppingCart.getInstance().addItem(new Item(
namePureString,
manufacturePureString,
pricePureString,
"",
count
));
}
}
This is my Singleton class, in which I call its methods:
public class ShoppingCart {
private static final String TAG = "Products: ";
private static ShoppingCart ourInstance = null;
public ArrayList<Item> myProducts = new ArrayList<>();
private ShoppingCart() {
}
public static ShoppingCart getInstance() {
// if object instance does not exist create a new one and use that one only
if ( ourInstance == null){
ourInstance = new ShoppingCart();
}
return ourInstance;
}
public void addItem(Item item){
ourInstance.myProducts.add(item);
}
public void setItemExists(Item item) {
int itemIndex = ourInstance.myProducts.indexOf(item);
if (itemIndex != -1) {
ourInstance.myProducts.set(itemIndex, item);
}
}
public List<Item> getProducts(){
return this.myProducts;
}
}
count++ is the same as count = count + 1 and not count += count in your Code. Count += count adds the amount of count on top of the value of count.
So to increment add this:
count = count + 1;
//or
count++;
Try
int count = 0;
count = count + 1;
Log.d("Answer: ",count);
Instead of count += count; try with count++;
Related
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
//
}
}
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
i'm using custom class to store user specific information class is as under:
using UnityEngine;
using System.Collections;
public class RoomPlayerInfo {
private int minutes;
private int seconds;
private int miliSecond;
private string userName;
public int Minutes{
get{ return minutes; }
set{ minutes = value;}
}
public int Seconds{
get{ return seconds; }
set{ seconds = value; }
}
public string UserName{
get{ return userName; }
set{ userName = value; }
}
public int MiliSecond{
get{ return miliSecond;}
set{ miliSecond = value;}
}
}
i'm adding user at runtime in a list:
private List<RoomPlayerInfo> listRoomPlayerInfo = new List<RoomPlayerInfo> ();
RoomPlayerInfo rPI = new RoomPlayerInfo ();
rPI.Minutes = diff.Minutes;
rPI.Seconds = diff.Seconds;
rPI.MiliSecond = diff.Milliseconds;
rPI.UserName = sfs.MySelf.Name;
listRoomPlayerInfo.Add (rPI);
When i'm going to remove a player at runtime, it only remove the currentPlayer on each device, mean on each device remove the own player of such device, but i'm going to remove the player which take max time in game..
How i can done my job ???
void RemovePlayer()
{
int i = 0;
int removePlayerIndex = 0;
if (listRoomPlayerInfo != null) {
string playerID = listRoomPlayerInfo [i].UserName;
for (; i < listRoomPlayerInfo.Count -1; i++) {
if (listRoomPlayerInfo [i + 1].Minutes >= listRoomPlayerInfo [i].Minutes && listRoomPlayerInfo [i + 1].Seconds > listRoomPlayerInfo [i].Seconds && listRoomPlayerInfo[i+1].MiliSecond > listRoomPlayerInfo[i].MiliSecond) {
playerID = listRoomPlayerInfo [i + 1].UserName;
removePlayerIndex = i + 1;
}
}
removeUserName.text = playerID + " Remove from room...";
listRoomPlayerInfo.Remove (listRoomPlayerInfo [removePlayerIndex]);
}
}
I'm writing a RealmMigration, and after several different errors during that, I think I finally got it but now I'm getting io.realm.exceptions.RealmMigrationNeededException: Index not defined for field 'primaryKey'.
I saw something about needing to use table.addSearchIndex(), but even after adding that for each of my tables I'm still getting the exception.
Here is my Migration class.
Migration.java
public class Migration implements RealmMigration {
#Override
public long execute(Realm realm, long version) {
Timber.i("Current database version: " + version);
/**
* Version 1:
* Task:
* Remove boolean field completed
* Remove Date field completedDate
* Transaction:
* Add int field type
*/
if (version == 0) {
// Transaction
Table transactionTable = realm.getTable(Transaction.class);
transactionTable.addColumn(ColumnType.INTEGER, "type");
long transactionPrimaryKeyIndex = getIndexForProperty(transactionTable, "primaryKey");
long transactionTitleIndex = getIndexForProperty(transactionTable, "title");
long transactionPointsIndex = getIndexForProperty(transactionTable, "points");
long transactionDateIndex = getIndexForProperty(transactionTable, "date");
long transactionTypeIndex = getIndexForProperty(transactionTable, "type");
for (int i = 0; i < transactionTable.size(); i++) {
// Until now the only possible transaction was reward
transactionTable.setLong(transactionTypeIndex, i, Transaction.TYPE_REWARD);
}
// Task
Table taskTable = realm.getTable(Task.class);
// Go through and create Transactions for each completed Task
long taskPrimaryKeyIndex = getIndexForProperty(taskTable, "primaryKey");
long taskCompletedIndex = getIndexForProperty(taskTable, "completed");
long taskCompletedDateIndex = getIndexForProperty(taskTable, "completedDate");
long taskTitleIndex = getIndexForProperty(taskTable, "title");
long taskPointsIndex = getIndexForProperty(taskTable, "points");
for (int i = 0; i < taskTable.size(); i++) {
if (taskTable.getBoolean(taskCompletedIndex, i)) {
transactionTable.addEmptyRowWithPrimaryKey(transactionTable.getLong(transactionPrimaryKeyIndex, transactionTable.size() - 1) + 1);
long j = transactionTable.size() - 1; // The new row
transactionTable.setString(transactionTitleIndex, j, taskTable.getString(taskTitleIndex, i));
transactionTable.setLong(transactionPointsIndex, j, taskTable.getLong(taskPointsIndex, i));
transactionTable.setDate(transactionDateIndex, j, taskTable.getDate(taskCompletedDateIndex, i));
transactionTable.setLong(transactionTypeIndex, j, Transaction.TYPE_TASK);
}
}
// Finally, remove the columns we don't need any more
taskTable.removeColumn(getIndexForProperty(taskTable, "completed"));
taskTable.removeColumn(getIndexForProperty(taskTable, "completedDate"));
// https://realm.io/news/realm-java-0.82.0/
taskTable.addSearchIndex(taskPrimaryKeyIndex);
transactionTable.addSearchIndex(transactionPrimaryKeyIndex);
Table reminderTable = realm.getTable(Reminder.class);
Table rewardTable = realm.getTable(Reward.class);
reminderTable.addSearchIndex(getIndexForProperty(reminderTable, "primaryKey"));
rewardTable.add(getIndexForProperty(rewardTable, "primaryKey"));
version++;
}
return version;
}
private long getIndexForProperty(Table table, String name) {
for (int i = 0; i < table.getColumnCount(); i++) {
if (table.getColumnName(i).equals(name)) {
return i;
}
}
return -1;
}
}
Task.java
public class Task extends RealmObject {
#PrimaryKey
private long primaryKey;
private String title;
private String description;
private int points;
private boolean hasReminders;
private RealmList<Reminder> reminders;
public static long getNextPrimaryKey(Realm realm) {
RealmResults<Task> tasks = realm.where(Task.class).findAllSorted("primaryKey");
if (tasks.size() == 0) return 0;
return tasks.last().getPrimaryKey() + 1;
}
// Getters and setters
}
Transaction.java
public class Transaction extends RealmObject {
public static final int TYPE_TASK = 0;
public static final int TYPE_REWARD = 1;
#PrimaryKey
private long primaryKey;
private String title;
private int points;
private Date date;
private int type;
public static long getNextPrimaryKey(Realm realm) {
if (realm != null) {
RealmResults<Transaction> transactions = realm.where(Transaction.class).findAllSorted("primaryKey");
if (transactions.size() == 0) return 0;
return transactions.last().getPrimaryKey() + 1;
} else {
return 0;
}
}
}
// Getters and setters
}
It is because you are removing two columns in the task table before adding the index. That means that the index you calculated in the beginning is no longer valid.
I am working with Section list view in Android to show Call details according to date.
Means under a particular date number of call details. But when I get 2 calls under the same date, the last date is visible only and the list does not show the rest of the calls of that date.
Calls under different dates are shown correctly but calls under same date are not shown correctly, only the last call is shown.
I am using the below code:
public String response = "{ \"Message\":\"Success\", "
+ "\"Data\":[ { \"ACCOUNT\":\"000014532497\", "
+ "\"DATE\":\"8/6/2006\", \"TIME\":\"15:37:14\", "
+ "\"CH_ITEM\":\"341T\", \"ITEM\":\"TIMEUSED\", "
+ "\"DESCRIPTION\":\"FROM3103475779\", \"DETAIL\":"
+ "\"UnitedKingdom011441980849463\", \"QUANTITY\":84, "
+ "\"RATE\":0.025, \"AMOUNT\":2.1, \"ACTUAL\":83.2, "
+ "\"NODE_NAME\":\"TNT02\", \"USER_NAME\":\"Shailesh Sharma\""
+ ", \"MODULE_NAME\":\"DEBIT\", \"ANI\":\"3103475779\", "
+ "\"DNIS\":\"3103210104\", \"ACCOUNT_GROUP\":\"WEBCC\", "
+ "\"SALES_REP\":\"sascha_d\", \"SALES_REP2\":\"\", \"SALES_REP3"
+ "\":\"\", \"IN_PORT\":\"I10\", \"EXTRA1\":\"RATE\", \"EXTRA2\":"
+ "\"44\", \"EXTRA3\":\"UnitedKingdom\", \"OUT_PORT\":\"I70\", "
+ "\"CRN\":\"WEBCC\", \"CallId\":null, \"ID\":4517734, \"PhoneNumber"
+ "\":\"011441980849463\" }, {\"ACCOUNT\":\"000014532497\",\"DATE\":"
+ "\"8/6/2006\",\"TIME\":\"09:22:57\",\"CH_ITEM\":\"541T\",\"ITEM\":"
+ "\"TIMEUSED\",\"DESCRIPTION\":\"FROM3103475779\",\"DETAIL\":"
+ "\"UnitedKingdom011447914422787\",\"QUANTITY\":1,\"RATE\":0.29,"
+ "\"AMOUNT\":0.29,\"ACTUAL\":0.5,\"NODE_NAME\":\"TNT02\",\"USER_NAME"
+ "\":\"Tusshar\",\"MODULE_NAME\":\"DEBIT\",\"ANI\":\"3103475779\",\"DNIS"
+ "\":\"6173950047\",\"ACCOUNT_GROUP\":\"WEBCC\",\"SALES_REP\":\"sascha_d"
+ "\",\"SALES_REP2\":\"\",\"SALES_REP3\":\"\",\"IN_PORT\":\"I30\",\"EXTRA1"
+ "\":\"RATE\",\"EXTRA2\":\"44\",\"EXTRA3\":\"UnitedKingdom-Special\","
+ "\"OUT_PORT\":\"I90\",\"CRN\":\"WEBCC\",\"CallId\":null,\"ID\":4535675,"
+ "\"PhoneNumber\":\"011447914422787\"}, ], \"NumberOfContacts\":2, "
+ "\"TotalCharges\":4.830000000000001 }";
try {
JSONObject jsonObj = new JSONObject(response);
String message = jsonObj.getString("Message");
if (message != null && message.equalsIgnoreCase("Success")) {
JSONArray dataArray = jsonObj.getJSONArray("Data");
System.out.println(dataArray.length());
for (int i = 0; i < dataArray.length(); i++) {
JSONObject history = dataArray.getJSONObject(i);
_date = history.getString("DATE");
String updatedDate = createDateFormat(_date);
// notes =new ArrayList<String>();
itemList = new ArrayList<Object>();
// ADDING DATE IN THE ARRAYLIST<String>
days.add(updatedDate);
_username = history.getString("USER_NAME");
_number = history.getString("PhoneNumber");
_time = history.getString("TIME");
_amount = history.getString("AMOUNT");
_duration = history.getString("QUANTITY");
/*
* notes.add(_username); notes.add(_number);
* notes.add(_time);
*/
AddObjectToList(_username, _number, _time, _amount,
_duration);
// listadapter = new <String>(this, R.layout.list_item,
// notes);
listadapter = new ListViewCustomAdapter(this, itemList);
adapter.addSection(days.get(i), listadapter);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public class SeparatedListAdapter extends BaseAdapter {
/*
* public final Map<String, Adapter> sections = new
* LinkedHashMap<String, Adapter>();
*/
public final Map<String, Adapter> sections = new LinkedHashMap<String, Adapter>();
public final ArrayAdapter<String> headers;
public final static int TYPE_SECTION_HEADER = 0;
public SeparatedListAdapter(Context context) {
headers = new ArrayAdapter<String>(context, R.layout.list_header);
}
public void addSection(String section, Adapter adapter) {
this.headers.add(section);
this.sections.put(section, adapter);
}
public Object getItem(int position) {
for (Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return section;
if (position < size)
return adapter.getItem(position - 1);
// otherwise jump into next section
position -= size;
}
return null;
}
public int getCount() {
// total together all sections, plus one for each section header
int total = 0;
for (Adapter adapter : this.sections.values())
total += adapter.getCount() + 1;
return total;
}
#Override
public int getViewTypeCount() {
// assume that headers count as one, then total all sections
int total = 1;
for (Adapter adapter : this.sections.values())
total += adapter.getViewTypeCount();
return total;
}
#Override
public int getItemViewType(int position) {
int type = 1;
for (Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return TYPE_SECTION_HEADER;
if (position < size)
return type + adapter.getItemViewType(position - 1);
// otherwise jump into next section
position -= size;
type += adapter.getViewTypeCount();
}
return -1;
}
public boolean areAllItemsSelectable() {
return false;
}
#Override
public boolean isEnabled(int position) {
return (getItemViewType(position) != TYPE_SECTION_HEADER);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int sectionnum = 0;
for (Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return headers.getView(sectionnum, convertView, parent);
if (position < size)
return adapter.getView(position - 1, convertView, parent);
// otherwise jump into next section
position -= size;
sectionnum++;
}
return null;
}
#Override
public long getItemId(int position) {
return position;
}
}
This is my actual requirement:
This is what is happening right now.
SectionListExampleActivity is my Main class in which I am getting RESPONSE from JSON web service. In getJSONResposne method I am calling the EntryAdaptor.
There are two separate geter setter classes for SECTION HEADER and ITEM ENTRY for each header.
public class SectionListExampleActivity extends Activity implements OnClickListener, OnItemSelectedListener, IServerResponse {
/** Called when the activity is first created. */
private ArrayList<Item> items = new ArrayList<Item>();
boolean firstTime = true;
private Spinner _spinner=null;
private ArrayAdapter _amountAdaptor = null;
private ArrayList<String> _monthList =new ArrayList<String>();
private ListView _list=null;
private Button _monthButton=null;
private ImageButton _backImageButton=null;
private ImageButton _headerImageButton=null;
private String _token;
private String _account;
private Point p=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.account_history);
String response = this.getIntent().getExtras().getString("history_resp");
_token = Constant.AUTH_TOKEN;
_account = Constant.ACCOUNT_NUM;
_list = (ListView)findViewById(R.id.listview);
getJSON_Response(response,Constant.PID_ACCOUNT_HISTORY);
EntryAdapter adapter = new EntryAdapter(this, items);
_list.setAdapter(adapter);
_monthList.add("Months");
_monthList.add("January");
_monthList.add("February");
_monthList.add("March");
_monthList.add("April");
_monthList.add("May");
_monthList.add("June");
_monthList.add("July");
_monthList.add("August");
_monthList.add("September");
_monthList.add("October");
_monthList.add("November");
_monthList.add("December");
_spinner = (Spinner)findViewById(R.id.month_spinner);
_amountAdaptor = new ArrayAdapter(this,
android.R.layout.simple_spinner_dropdown_item,
_monthList);
_spinner.setAdapter(_amountAdaptor);
_spinner.setOnItemSelectedListener(this);
_monthButton = (Button)findViewById(R.id.monthSpinner_button);
_monthButton.setOnClickListener(this);
_backImageButton = (ImageButton)findViewById(R.id.back_ImageButton);
_backImageButton.setOnClickListener(this);
_headerImageButton =(ImageButton)findViewById(R.id.header_ImageButton);
_headerImageButton.setOnClickListener(this);
}
private void getJSON_Response(String response,int pid) {
switch (pid) {
case Constant.PID_ACCOUNT_HISTORY:
try {
JSONObject jsonObj = new JSONObject(response);
String message = jsonObj.getString("Message");
if(message!=null && message.equalsIgnoreCase("Success")){
JSONArray dataArray = jsonObj.getJSONArray("Data");
System.out.println(dataArray.length());
String lastAddedDate = null;
for (int i = 0; i <dataArray.length(); i++) {
JSONObject history = dataArray.getJSONObject(i);
String date = history.getString("DATE");
if(firstTime || !(date.equalsIgnoreCase(lastAddedDate))){
firstTime=false;
lastAddedDate = date;
items.add(new SectionItem(date));
}
String username= history.getString("USER_NAME");
String number = history.getString("PhoneNumber");
String time = history.getString("TIME");
String amount=history.getString("AMOUNT");
String duration =history.getString("QUANTITY");
items.add(new EntryItem(username,duration,amount,number,time));
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default:
break;
}
}
#Override
public void onClick(View v) {
if(v==_monthButton){
_spinner.performClick();
}else if(v==_backImageButton){
SectionListExampleActivity.this.finish();
}else if(v== _headerImageButton){
if (p != null)
showPopup(SectionListExampleActivity.this, p);
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View v, int position,
long arg3) {
if(position!=0){
switch (parent.getId()) {
case R.id.month_spinner:
String selectedItem = _spinner.getSelectedItem().toString();
_monthButton.setBackgroundResource(R.drawable.month_blank);
_monthButton.setText(selectedItem);
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
String _historyURL = Constant.prodORdevUrl + "GetAccountHistory?token="+_token+"&account="+_account+"&month="+month+"&year="+year;
getHistory(_historyURL,true);
break;
default:
break;
}
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
public class EntryAdapter extends ArrayAdapter<Item> implements IServerResponse {
private Context context;
private ArrayList<Item> items;
private LayoutInflater vi;
private String _token;
private String _account;
public EntryAdapter(Context context,ArrayList<Item> items) {
super(context,0, items);
this.context = context;
this.items = items;
vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
_token = Constant.AUTH_TOKEN;
_account = Constant.ACCOUNT_NUM;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
final Item i = items.get(position);
if (i != null) {
if(i.isSection()){
SectionItem si = (SectionItem)i;
v = vi.inflate(R.layout.list_item_section, null);
v.setOnClickListener(null);
v.setOnLongClickListener(null);
v.setLongClickable(false);
final TextView sectionView = (TextView) v.findViewById(R.id.list_item_section_text);
String date =createDateFormat(si.getTitle());
sectionView.setText(date);
}else{
EntryItem ei = (EntryItem)i;
v = vi.inflate(R.layout.list_item_entry, null);
final RelativeLayout relay = (RelativeLayout)v.findViewById(R.id.account_history_item_relay);
final TextView username = (TextView)v.findViewById(R.id.user_name_textview);
final TextView amount = (TextView)v.findViewById(R.id.amount_textview);
final TextView duration = (TextView)v.findViewById(R.id.duration_textview);
final TextView phone = (TextView)v.findViewById(R.id.phone_no_textview);
final TextView time = (TextView)v.findViewById(R.id.time_textview);
relay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
makeCall(phone.getText().toString());
}
});
if (username != null)
username.setText(ei.username);
if(amount != null)
amount.setText(ei.duration + "min");
if(duration != null)
duration.setText("$"+ ei.amount);
if(phone != null)
phone.setText(ei.number);
if(time != null)
time.setText(ei.time);
}
}
return v;
}
void makeCall(String destination) {
if(_token!=null && _account!=null){
if(destination!=null && !destination.equals("")){
String phoneNumber = Constant.getPhoneNumber(this.context.getApplicationContext());
if(phoneNumber!=null && phoneNumber.length()>0){
String callURL =WebService.WEB_SERVICE_URL+"PlaceLongDistanceCall?token="+_token +
"&phonenumber="+phoneNumber+"&destinationNumber="+destination+"&authtoken="+_token;
getCall(callURL,true);
}else{
Constant.showToast(this.context, Constant.INSERT_SIM);
}
}else{
Constant.showToast(this.context, "In valid destination number.");
}
}
}
}