I display in a list view some team members. The plan is to get the teamId with the maximum number of steps. The below method demonstrates how I am achieving that.
public void readLeagueMembers(JSONObject response){
JSONArray teamsArray = null;
try {
teamsArray = response.getJSONArray("teams");
for (int i = 0; i < teamsArray.length(); i++) {
leagueMembers = new LeagueMembers();
JSONObject team = teamsArray.getJSONObject(i);
leagueMembers.setTeamId(team.getString("ID"));
leagueMembers.setTeams(team.getString("team_name"));
leagueMembers.setLeaguePoints(team.getString("team_points"));
leagueMembersList.add(leagueMembers);
listView.setAdapter(leagueAdapter);
//String[] team_points = new String[]{leagueMembers.getLeaguePoints()};
teamId = leagueMembersList.get(0).getTeamId();
Log.d("teamId",teamId);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
You see from that method the variable teamId(which is static) where it stores the first row's teamId which is 645.
Now I am passing this value to another class which is a CountDownTimer one.
public class CounterClass1 extends CountDownTimer {
public CounterClass1(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
long seconds = millisUntilFinished / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
String time = days+"d"+ ":" + hours % 24+"h" + ":" + minutes % 60 +"m"+ ":" + seconds % 60+"s";
diffDays.setText("League finishes in: " + time);
}
#Override
public void onFinish() {
diffDays.setText("League Finished");
viewResults.setVisibility(View.VISIBLE);
leagueInvitation.setVisibility(View.GONE);
winnerId = League.teamId;
Log.d("team id",winnerId);
viewResults(leagueId, winnerId, results, username, password);
}
}
As shown I read the static variable teamId from another class
winnerId = League.teamId;
and store it to a variable called winnerId. Unfortunately winnerId is read as null from the debugger. Any suggestions? Surely it is a Java problem not an Android one.
Thanks.
First of all where is your leagueadapter. Whare you initialize it . And second thing you are setting adapter inside loop that is wrong. It will set adpter again and again if you have more that one oblect inside json array .
And for the team id you can create a singleton class and set team id there in a instance varible .and get that id whereever you want .Here is tha code fro singleton class you need .
public class ReferenceWrapper {
private static ReferenceWrapper wrapper;
private int teamId;
private Context context;
private ReferenceWrapper(Context context) {
this.context=context;
}
public static ReferenceWrapper getInstance(Context context) {
if (wrapper == null) {
wrapper = new ReferenceWrapper(context);
}
return wrapper;
}
public int getTeamId(int teamId) {
return teamId;
}
public int setTeamId() {
this.teamId=teamId;
}
}
Related
Im currently working on a little mobile game in which you throw spears at targets, and depending on how many spears you have left at the end of the level you get between one and three Runes (similar to the Star scoring sytem in Angry Birds). The plan is to save the runes and use them to unlock different spear variants in the Main Menu.
At the moment you can see how many runes you got after completeing the level, but the values are not yet being saved.
My question is, how would I go about saving the Runes after each Level? Any ideas? You can see the part of the script Im using for that below. Thanks in advance.
public int totalRunes = 0;
public GameObject rune1;
public GameObject rune2;
public GameObject rune3;
public void RuneCollection()
{
if (currentSpears >= 2)
{
Debug.Log("3 runes collected!");
rune3.SetActive(true);
totalRunes = 3;
}
else if (currentSpears >= 1)
{
Debug.Log("2 runes collected!");
rune2.SetActive(true);
totalRunes = 2;
}
else
{
Debug.Log("1 rune collected!");
rune1.SetActive(true);
totalRunes = 1;
}
}
I would use Unitys PlayerPrefs System.
Example:
Setting Score:
public Text score;
int currentscore = 0;
Increasing Score:
currentscore += 1;
score.text = currentscore.ToString();
Setting HighScore and Loading Menu:
GameManager.SetHighScore(currentscore);
SceneManager.LoadScene("Menu");
Functions to Load/Change PlayerPrefs:
void Start()
{
highscore.text = PlayerPrefs.GetInt("HighScore", 0).ToString();
}
public static void SetHighScore(int score)
{
if (score > PlayerPrefs.GetInt("HighScore", 0))
{
PlayerPrefs.SetInt("HighScore", score);
}
}
Your Code adapted to PlayerPrefs:
public int currentSpears = 0;
public GameObject rune1;
public GameObject rune2;
public GameObject rune3;
void Start()
{
currentSpears = PlayerPrefs.GetInt("CurrentSpears", 0).ToString();
}
public static void IncreaseSpears()
{
int spears = PlayerPrefs.GetInt("CurrentSpears", 0);
PlayerPrefs.SetInt("CurrentSpears", spears++);
}
public void RuneCollection()
{
if (currentSpears >= 2)
{
Debug.Log("3 runes collected!");
rune3.SetActive(true);
totalRunes = 3;
}
else if (currentSpears >= 1)
{
Debug.Log("2 runes collected!");
rune2.SetActive(true);
totalRunes = 2;
}
else
{
Debug.Log("1 rune collected!");
rune1.SetActive(true);
totalRunes = 1;
}
}
You can save your data with PlayerPrefs for some single values or PersistentDataPath for some multiple values such as a class. Find out more with this link, and you can use them as below.
PlayerPrefs:
private int score = 0;
//set value
PlayerPrefs.SetInt("Score", score);
//get value
private int savedScore = PlayerPrefs.GetInt("Score");
PersistentDataPath:
private string savedName;
private int savedHealth;
private string loadedName;
private int loadedHealth;
public void Save(){
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/FileName.dat",
FileMode.Create);
PlayerClass newData = new PlayerClass();
newData.health = savedHealth;
newData.name = savedName;
bf.Serialize(file, newData);
file.Close();
}
public void Load(){
if (File.Exists(Application.persistentDataPath + "/FileName.dat")){
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/FileName.dat", FileMode.Open);
ObjData newData = (ObjData)bf.Deserialize(file);
file.Close();
loadedHealth = newData.health;
loadedName = newData.name;
}
}
[Serializable]
class PlayerClass{
public string name;
public int health;
}
I need help for this load more RecycleView, I create 'Recyclerview', first, limit 5 data and showing, but when I scroll until the end no 'ProgressBar' showing and the next data now showing, I check the 'logcat' no error only warning
this my load more function
private void loadMore() {
arraylist.add(null);
mListadapter.notifyItemInserted(arraylist.size() - 1);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
arraylist.remove(arraylist.size() - 1);
int scrollPosition = arraylist.size();
mListadapter.notifyItemRemoved(scrollPosition);
int currentSize = scrollPosition;
int nextLimit = currentSize + 5;
Log.e("currentSize",""+currentSize);
Log.e("nextLimit",""+nextLimit);
if(nextLimit <= DataNoteImformation.id.length) {
while (currentSize + 1 <= nextLimit) {
DataNote wp2 = new DataNote(
DataNoteImformation.id[currentSize],
DataNoteImformation.branchArray[currentSize],
DataNoteImformation.assetcodeArray[currentSize],
DataNoteImformation.customerArray[currentSize],
DataNoteImformation.licenseplateArray[currentSize]
);
arraylist.add(wp2);
currentSize++;
}
}else {
while (currentSize + 1 <= DataNoteImformation.id.length) {
DataNote wp2 = new DataNote(
DataNoteImformation.id[currentSize],
DataNoteImformation.branchArray[currentSize],
DataNoteImformation.assetcodeArray[currentSize],
DataNoteImformation.customerArray[currentSize],
DataNoteImformation.licenseplateArray[currentSize]
);
arraylist.add(wp2);
currentSize++;
}
}
mListadapter.notifyDataSetChanged();
isLoading = false;
}
}, 2000);
}
and the warning in logcat
W/RecyclerView: Cannot call this method in a scroll callback. Scroll callbacks might be run during a measure & layout pass where you cannot change theRecyclerView data. Any method call that might change the structure of the RecyclerView or the adapter contents should be postponed to the next frame.
and this example data
public class DataNoteImformation {
public static String[] branchArray = {"Depok","Jakarta","Bekasi","Jakarta","Jakarta","Bekasi","Bogor","Jakarta","Bekasi","Jakarta"};
public static String[] assetcodeArray = {"0092","0084","0091","0084","0084","0078","0089","0073","0027","0021"};
public static String[] customerArray = {"Kevin Sanjaya","Indah Permata","Riyan","Puri Setiawan","Herman","Iwan","Ratna","Agus","Danang","Ujang"};
public static String[] licenseplateArray = {"B 9829 SK","B 8294 LK","B 9090 NBA","B 7627 SKA","B 7637 SAK","B 6763 KIK","F 7287 NB","F8792KI","B8273KD","B7728KSI"};
public static String[] id = {"1","2","3","4","5","6","7","8","9","10"};
}
how to fix this.
My current data structure is as follows:
public class MyDataTemplate {
long occurenceTime;
int val1;
int val2;
public MyDataTemplate(Long nanoTime, int val1, int val2) {
this.occurenceTime = nanoTime;
this.val1 = val1;
this.val2 = val2;
}
}
List<MyDataTemplate> myData = new ArrayList <MyDataTemplate>();
The occurenceTime(long) above represents the system time which I obtain in Android using System.nanoTime()
If data arrived sequentially by time, I could have very well used the above data structure to store data as and when it arrives:
newOccurence = new MyDataTemplate(System.nanoTime(), 42, 55)
myData.add(newOccurence);
However, since data does not arrive sequentially, I may get a new occurrence earlier than an old occurrence.
My task is to ensure that the myData contains data in ascending order of time, irrespective of when it arrives.
How can I ensure that ?
Froggy Oat...
I have made an attempt which seems to loosely illustrate a potential "solution:"
public class MainActivity extends AppCompatActivity {
public class MyDataTemplate {
long occurenceTime;
int val1;
int val2;
public MyDataTemplate(Long nanoTime, int val1, int val2) {
this.occurenceTime = nanoTime;
this.val1 = val1;
this.val2 = val2;
}
}
class SortByNanoTime implements Comparator<MyDataTemplate> {
public int compare(MyDataTemplate a, MyDataTemplate b) {
if (a.occurenceTime < b.occurenceTime)
return -1;
else if (a.occurenceTime > b.occurenceTime)
return +1;
else
return 0;
}
}
List<MyDataTemplate> myData = new ArrayList<MyDataTemplate>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myData.add(new MyDataTemplate((long) 30000.2341, 2, 3));
myData.add(new MyDataTemplate((long) 234234.234, 3, 4));
myData.add(new MyDataTemplate((long) 11234234.234, 3, 4));
myData.add(new MyDataTemplate((long) 4.234, 3, 4));
Collections.sort(myData, new SortByNanoTime());
for (MyDataTemplate tempVar : myData) {
Log.i("XXX", "" + tempVar.occurenceTime);
}
}
}
You will want to use a priority queue or a tree set - - since your timestamps are nanos, the Comparator is simply a normal Integer compare.
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 using a Chronometer in my Android App. I can start it, stop it and continue counting after pushing the start button again:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_projektbeschreibung, container, false);
if (savedInstanceState != null){
stoppedmillis = savedInstanceState.getLong(STATE_TIME);
hh = savedInstanceState.getString(STATE_HH);
mm = savedInstanceState.getString(STATE_MM);
ss = savedInstanceState.getString(STATE_SS);
}
mChronometer = (Chronometer) rootView.findViewById(R.id.chronometer2);
mChronometer.setText(hh + ":" + mm + ":" + ss);
mChronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer cArg) {
long time = SystemClock.elapsedRealtime() - cArg.getBase() ;
int h = (int) (time / 3600000);
int m = (int) (time - h * 3600000) / 60000;
int s = (int) (time - h * 3600000 - m * 60000) / 1000;
hh = h < 10 ? "0" + h : h + "";
mm = m < 10 ? "0" + m : m + "";
ss = s < 10 ? "0" + s : s + "";
cArg.setText(hh + ":" + mm + ":" + ss);
}
});
((Button) rootView.findViewById(R.id.startbutton)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//if first start
if(stoppedmillis == 0) {
mChronometer.setBase(SystemClock.elapsedRealtime());
} else {//Point A
long pausetime = (SystemClock.elapsedRealtime() - stoppedmillis);
mChronometer.setBase(mChronometer.getBase() + pausetime);
}
mChronometer.start();
}
});
((Button) rootView.findViewById(R.id.stopbutton)).setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
mChronometer.stop();
stoppedmillis = SystemClock.elapsedRealtime();
}
});
After a screen rotation (so the Activity restarts) the chronometer starts counting from the point of 00:00:00 again. My first try was to save the stoppedmillis with a onSaveInstanceState method like the following:
public void onSaveInstanceState(Bundle savedInstanceState){
savedInstanceState.putLong(STATE_TIME, stoppedmillis);
savedInstanceState.putString(STATE_HH, hh);
savedInstanceState.putString(STATE_MM, mm);
savedInstanceState.putString(STATE_SS,ss);
super.onSaveInstanceState(savedInstanceState);
}
Now, I can get the value of the stoppedmillis after a restart, but I don't know how to set the Base for the Chronometer with the help of the stoppedmillis. At Point A in the Code you can see how it works with stopping the Chronometer with a button but this part of code does not working after a screen rotation.
I know that this is old. Although, I have created a simple application using a chronometer and done the following and it has kept counting across screen rotation. It is spot on with Andrew's original answer. Here is how I outlined it:
Chronometer mChronometer; // this is a global variable
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChronometer = (Chronometer)findViewById(R.id.chronometer);
if(savedInstanceState != null){
mChronometer.setBase(savedInstanceState.getLong("ChronoTime"));
mChronometer.start();
}
}
Now set up onSaveInstanceState:
#Override
public void onSaveInstanceState (Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putLong("ChronoTime", mChronometer.getBase());
}
Fast solution, using this class:
https://github.com/ahmedrizwan/ChronometerPersist/blob/master/chronometerpersist/src/main/java/library/minimize/com/chronometerpersist/ChronometerPersist.java
ChronometerPersist chronometerPersist = ChronometerPersist.getInstance(chronometer, sharedPreferences);
//Starting the chronometer
startChronometer();
//Stoping the chronometer
stopChronometer();
//Pausing the chronometer
pauseChronometer();
I have lost much time trying to restore the current time with the android chronometer widget.
This is how i solved saving the state of the Chronometer.
private static final int TIME_MULTIPLIER = 60;
Step 1: Convert time to Seconds:
NOTE: If you don't like my method of converting time to second you could do your ways.
private static int convertTimeToSeconds(Long... time) {
int seconds = 0;
if (time.length == 2) {
seconds += time[0] * TIME_MULTIPLIER + time[1];
} else if (time.length == 3) {
seconds += (time[0] * TIME_MULTIPLIER) + (time[1] * TIME_MULTIPLIER) + (time[2]);
}
return seconds;
}
Step 2: Setting and starting time of Chronometer
NOTE: I'm saving the data in a custom object persist that object with any database / SharedPreference / your wish.
public static void setAndStartTime(final Chronometer chronometer) {
long second = 0;
// i have multiple time saved into map. You could save just 1 time and reuse that time.
for (DailyData data : DailyData.DailyDataHolder.getDailyDataMap().values()) {
second += data.getDailyTimeSpent();
}
chronometer.setBase(SystemClock.elapsedRealtime() - (second * 1000));
chronometer.start();
}
Step 3: Saving Time:
public static void saveTime(String timeText) {
String[] timeParts = timeText.split("[:]");
long savedTime = 0;
if (timeParts.length == 2) {
savedTime = convertTimeToSeconds(Long.parseLong(timeParts[0]), Long.parseLong(timeParts[1]));
} else if (timeParts.length == 3) {
savedTime = convertTimeToSeconds(Long.parseLong(timeParts[0]), Long.parseLong(timeParts[1]), Long.parseLong(timeParts[2]));
}
DailyData.DailyDataHolder.getDailyData().setDailyTimeSpent(savedTime);
}
Calling the saved method:
ChronoHelper.saveTime(chronometer.getText().toString());
COMPLETE CLASS:
public class ChronoHelper {
private static final int TIME_MULTIPLIER = 60;
public static void setAndStartTime(final Chronometer chronometer) {
long second = 0;
for (DailyData data : DailyData.DailyDataHolder.getDailyDataMap().values()) {
second += data.getDailyTimeSpent();
}
chronometer.setBase(SystemClock.elapsedRealtime() - (second * 1000));
chronometer.start();
}
public static void saveTime(String timeText) {
String[] timeParts = timeText.split("[:]");
long savedTime = 0;
if (timeParts.length == 2) {
savedTime = convertTimeToSeconds(Long.parseLong(timeParts[0]), Long.parseLong(timeParts[1]));
} else if (timeParts.length == 3) {
savedTime = convertTimeToSeconds(Long.parseLong(timeParts[0]), Long.parseLong(timeParts[1]), Long.parseLong(timeParts[2]));
}
DailyData.DailyDataHolder.getDailyData().setDailyTimeSpent(savedTime);
}
private static int convertTimeToSeconds(Long... time) {
int seconds = 0;
if (time.length == 2) {
seconds += time[0] * TIME_MULTIPLIER + time[1];
} else if (time.length == 3) {
seconds += (time[0] * TIME_MULTIPLIER) + (time[1] * TIME_MULTIPLIER) + (time[2]);
}
return seconds;
}
public static String secondsToTimeText(DailyData dailyData) {
long savedSeconds = dailyData.getDailyTimeSpent();
long minutes = savedSeconds / TIME_MULTIPLIER;
long seconds = savedSeconds % TIME_MULTIPLIER;
long hours = minutes / TIME_MULTIPLIER;
return hours + ":" + minutes + ":" + seconds;
}
}
Save the base time of the chronometer in onSaveInstanceState and set it back in onRestoreInstanceState like this:
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putLong("ChronoTime", mChronometer.getBase());
super.onSaveInstanceState(savedInstanceState);
}
public void onRestoreInstanceState(Bundle savedInstanceState){
if((savedInstanceState !=null) && savedInstanceState.containsKey("ChronoTime"))
mChronometer.setBase(savedInstanceState.getLong("ChronoTime"));
super.onRestoreInstanceState(savedInstanceState);
}