I have problem with updating progressbar. If I check checkbox, file is automaticaly copied but progress is still 0. I use SwingWokrer, but I don't know how I can progressbar updating.
I tried many combinations, but it does not work.
This code is responsible for downloading the file from the selected row.
jTable.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel tableModel = (TableModel) e.getSource();
Boolean dataObject = (Boolean) tableModel.getValueAt(row,column);
String fileNameToCopy = (String) tableModel.getValueAt(row, 0);
Long fileSize = (Long) tableModel.getValueAt(row, 1);
Float progress = (Float) tableModel.getValueAt(row, 3);
if (dataObject == true) {
customTableData.setFile(new File(fileNameToCopy));
customTableData.setFileSize(fileSize);
customTableData.setProgress(progress);;
copyFiles = new CopyFiles(customTableData);
}
}
});
CustomTableData.java
public class CustomTableData {
private File file;
private long fileSize;
private Boolean edit = false;
private float progress;
public CustomTableData() {}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public Boolean isEdit() {
return edit;
}
public void setEdit(Boolean edit) {
this.edit = edit;
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
}
}
My CopyFiles.java class
private String fileName;
private long fileSize;
private float progress;
private CustomTableData data;
public CopyFiles(CustomTableData data) {
this.data = new CustomTableData();
this.fileName = data.getFile().getName();
this.fileSize = data.getFileSize();
this.progress = data.getProgress();
worker.execute();
}
SwingWorker<Void, Float> worker = new SwingWorker<Void, Float>(){
#Override
protected Void doInBackground() throws Exception {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source + fileName);
os = new FileOutputStream(destination + fileName);
byte[] buffer = new byte[BUFFER];
int length = 0;
float pro = 0;
while((length = is.read(buffer)) != -1) {
publish(pro += length);
os.write(buffer, 0, length);
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
is.close();
os.close();
} catch (IOException e) {
e.getMessage();
}
}
return null;
}
protected void process(java.util.List<Float> chunks) {
for (Float f : chunks) {
progress = (f*100) / fileSize;
System.out.println("Percentage progress: " + progress + " >>> file size: " + f);
}
};
protected void done() {
System.out.println("FILE: " + fileName + " SIZE: " + fileSize);
};
};
}
And my CustomTableModel.java class
public class CustomTableModel extends AbstractTableModel {
private static final long serialVersionUID = -2929662905556163705L;
#SuppressWarnings("unused")
private File dir;
private File[] fileArray;
private List<CustomTableData> filesList;
private CustomTableData fileRow;
public CustomTableModel(File dir) {
this.dir = dir;
this.filesList = new ArrayList<CustomTableData>();
this.fileArray = dir.listFiles();
fileLoop();
}
private void fileLoop() {
for (int i = 0; i < fileArray.length; i++) {
this.fileRow = new CustomTableData();
if (fileArray[i].isFile()) {
fileRow.setFile(fileArray[i]);
fileRow.isEdit();
fileRow.getProgress();
filesList.add(fileRow);
}
}
}
private ResourceBundle resourceBundle = ResourceBundle.getBundle("MessageBundle", Locale.forLanguageTag("pl"));
protected String[] columns = new String[] {
resourceBundle.getString("fileName"),
resourceBundle.getString("fileSize") + " [byte]",
resourceBundle.getString("getFile"),
resourceBundle.getString("progress")};
#SuppressWarnings("rawtypes")
protected Class[] columnClasses = {String.class , Long.class, JCheckBox.class, JProgressBar.class};
public int getColumnCount() {
return columns.length;
}
public int getRowCount() {
return filesList.size();
}
public String getColumnName(int col) {
return columns[col].toString();
}
public Class<?> getColumnClass(int c) {
switch (c) {
case 0:
return String.class;
case 1:
return Long.class;
case 2:
return Boolean.class;
case 3:
return Float.class;
default:
return null;
}
}
public Object getValueAt(int row, int col) {
fileRow = filesList.get(row);
switch (col) {
case 0:
return fileRow.getFile().getName();
case 1:
return fileRow.getFile().length();
case 2:
return fileRow.isEdit();
case 3:
return fileRow.getProgress();
default:
return null;
}
}
public boolean isCellEditable(int row, int col) {
switch (col) {
case 0:
return false;
case 1:
return false;
case 2:
return true;
case 3:
return false;
default:
return false;
}
}
public void setValueAt(Object aValue, int row, int column) {
fileRow = filesList.get(row);
if (column == 2) {
fileRow.setEdit((Boolean)aValue);
fireTableCellUpdated(row, column);
}
}
}
This is my ProgressBarRenderer.java class
public class ProgressBarRenderer extends JProgressBar implements TableCellRenderer {
private static final long serialVersionUID = 551156559687881082L;
public ProgressBarRenderer() {
super();
}
public ProgressBarRenderer(int min, int max) {
super(min, max);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setValue((int) ((Float) value).floatValue());
return this;
}
}
My table view
Rozwiązanie
Progressbar jest prawidłowo aktualizowany w metodzie process()
public class CopyFiles {
private static final int BUFFER = 1024;
private int row;
private CustomTableModel customTableModel;
private String fileName;
private File file;
public CopyFiles(String fileName, CustomTableModel customTableModel, int row) {
this.fileName = fileName;
this.file = new File(PathEnum.SOURCE.getPath() + fileName);
this.customTableModel = customTableModel;
this.row = row;
worker.execute();
}
public String getFile() {
return file.getName();
}
public long getFileSize() {
return file.length();
}
public SwingWorker<Void, Float> getWorker() {
return worker;
}
SwingWorker<Void, Float> worker = new SwingWorker<Void, Float>() {
#Override
protected Void doInBackground() throws Exception {
InputStream is = null;
OutputStream os = null;
float progress = 0;
try {
is = new FileInputStream(PathEnum.SOURCE.getPath() + getFile());
os = new FileOutputStream(PathEnum.DESTINATION.getPath() + getFile());
byte[] buffer = new byte[BUFFER];
long count = 0;
int bufferLength;
while ((bufferLength = is.read(buffer)) != -1) {
count += bufferLength;
os.write(buffer, 0, bufferLength);
progress = (int) ((count * 100) / getFileSize());
publish(progress);
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
is.close();
os.close();
} catch (IOException e) {
e.getMessage();
}
}
return null;
}
protected void process(List<Float> chunks) {
float currentProgress = chunks.get(chunks.size()-1);
customTableModel.setValueAt(currentProgress, row, 3);
};
protected void done() {
System.out.println("FILE: " + getFile() + " SIZE: " + getFileSize());
};
};
Related
I'm developing a Sudoku app on Android and I can't prevent my custom view (the sudoku board) to draw over itself. I'm quite new to app development, so I can't understand what's happening. Basically when I pass a board to the GameActivity the custom view in there draws the new board over the older ones. This should not happen. Any help would be appriciated.
This is my custom View.
public class SudokuBoardView extends View {
private static final String TAG = "SUDOKUVIEWGRID";
//Paints
private Paint thinPaint;
private Paint thickPaint;
private Paint selectedCellPaint;
private Paint textPaint;
//Values
private static int width;
private static int height;
private static final int padding = 64;
private static final int SIZE = 9;
private static final int SQRT_SIZE = 3;
private float cellSizePixels;
//Model
private SudokuModel sudokuModel = null;
public SudokuBoardView(Context context) {
super(context);
init(null);
}
public SudokuBoardView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public SudokuBoardView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public SudokuBoardView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
public void init(#Nullable AttributeSet attributeSet) {
//Paint più sottile per celle
thinPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thinPaint.setStrokeWidth(2);
thinPaint.setStyle(Paint.Style.STROKE);
thinPaint.setColor(Color.BLACK);
//Paint più spesso per contorni
thickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thickPaint.setStrokeWidth(10);
thickPaint.setStyle(Paint.Style.STROKE);
thickPaint.setColor(Color.BLACK);
//Paint per celle selezionate
selectedCellPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
selectedCellPaint.setColor(Color.BLUE);
selectedCellPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//Paint per numeri
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(32);
textPaint.setColor(Color.BLACK);
//Dimensioni della griglia e delle celle
width = getResources().getDisplayMetrics().widthPixels; //Dim. assoluta dello schermo
height = getResources().getDisplayMetrics().heightPixels;
cellSizePixels = (float) ((width - 2*padding)/ SIZE);
}
public void setSudokuModel(SudokuModel model) {
this.sudokuModel = model;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Outside Border
canvas.drawRoundRect(padding,padding, width - padding, width - padding, 20, 20, thickPaint);
//Cells
drawLines(canvas);
if (sudokuModel.isNewGame()) {
drawInitialBoard(canvas, sudokuModel.getBoard());
}
}
public void cleanCells() {
invalidate();
}
protected void drawLines(Canvas canvas){
//Linee Verticali
for (int i = 0; i < SIZE; i++) {
//Linea più spessa ogni 3 linee (la prima viene saltata perché c'è già il bordo)
if (i == 0) continue;
if (i % SQRT_SIZE == 0) {
canvas.drawLine( i*cellSizePixels + padding, padding, i*cellSizePixels + padding, width - padding, thickPaint);
} else {
canvas.drawLine( i*cellSizePixels + padding, padding, i*cellSizePixels + padding, width - padding, thinPaint);
}
}
//Linee Orizzontali
for (int i = 0; i < SIZE; i++) {
//Linea più spessa ogni 3 linee (la prima viene saltata perché c'è già il bordo)
if (i == 0) continue;
if (i % SQRT_SIZE == 0) {
canvas.drawLine( padding, i*cellSizePixels + padding, width - padding, i*cellSizePixels + padding, thickPaint);
} else {
canvas.drawLine(padding, i * cellSizePixels + padding, width - padding, i * cellSizePixels + padding, thinPaint);
}
}
}
public void drawInitialBoard(Canvas canvas, Board board) {
for (Cell cell: board.getCellList()) {
int value = cell.getValue();
String valueText = Integer.toString(value);
int row = cell.getRow();
int col = cell.getCol();
Rect textBounds = new Rect();
textPaint.getTextBounds(valueText, 0, valueText.length(), textBounds);
float textWidth = textPaint.measureText(valueText);
float textHeight = textBounds.height();
canvas.drawText((value == 0 ? "" : valueText), (row * cellSizePixels + cellSizePixels/2 - textWidth/2 + padding), (col*cellSizePixels + cellSizePixels/2 + thickPaint.getStrokeWidth() + padding), textPaint);
}
}
}
And this is the GameActivity where the view is.
public class GameActivity extends AppCompatActivity {
//Controls Buttons
Button[] buttons = new Button[10];
private static final int[] BUTTON_IDS = {
R.id.button1,
R.id.button2,
R.id.button3,
R.id.button4,
R.id.button5,
R.id.button6,
R.id.button7,
R.id.button8,
R.id.button9,
R.id.buttonCancel
};
NumbersOnClickListener numbersOnClickListener;
private Board board;
private SudokuModel sudokuModel;
private SudokuBoardView sudokuBoardView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
/*
* NEW GAME
*
* Board Setup
* */
Intent gameIntent = getIntent();
boolean isNewGame = gameIntent.getBooleanExtra("new game", false);
if (isNewGame) {
board = gameIntent.getParcelableExtra("Board");
sudokuModel = new SudokuModel(board, isNewGame);
sudokuModel.getBoard().printBoard();
sudokuBoardView = findViewById(R.id.sudokuView);
sudokuBoardView.setSudokuModel(sudokuModel);
}
//Controls Setup
numbersOnClickListener = new NumbersOnClickListener();
for (int i = 0; i < 10; i++) {
buttons[i] = findViewById(BUTTON_IDS[i]);
buttons[i].setOnClickListener(numbersOnClickListener);
GridLayout.LayoutParams params = (GridLayout.LayoutParams) buttons[i].getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 7;
params.height = params.width;
buttons[i].setLayoutParams(params);
}
}
#Override
protected void onPause() {
super.onPause();
}
}
The SudokuModel class.
public class SudokuModel {
private Board board;
private boolean isNewGame;
private int selectedRow = -1;
private int selectedCol = -1;
public SudokuModel(Board board, boolean isNewGame) {
this.board = board;
this.isNewGame = isNewGame;
}
public Board getBoard() {
return board;
}
public void setBoard(Board board) {
this.board = board;
}
public boolean isNewGame() {
return isNewGame;
}
public int getSelectedRow() {
return selectedRow;
}
public int getSelectedCol() {
return selectedCol;
}
public void setSelectedRow(int selectedRow) {
this.selectedRow = selectedRow;
}
public void setSelectedCol(int selectedCol) {
this.selectedCol = selectedCol;
}
}
The Board class.
public class Board implements Parcelable {
private static final int SIZE = 9;
private ArrayList<Cell> cellList = new ArrayList<>();
public Board(ArrayList<Cell> cellList) {
this.cellList = cellList;
}
public ArrayList<Cell> getCellList() {
return cellList;
}
public void setCellList(ArrayList<Cell> cellList) {
this.cellList = cellList;
}
public void printBoard () {
for (Cell cell: cellList) {
System.out.println("Cell " + cell.getRow() + ":" + cell.getCol() + " VALUE: " + cell.getValue());
}
}
protected Board(Parcel in) {
if (in.readByte() == 0x01) {
cellList = new ArrayList<Cell>();
in.readList(cellList, Cell.class.getClassLoader());
} else {
cellList = null;
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (cellList == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(cellList);
}
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Board> CREATOR = new Parcelable.Creator<Board>() {
#Override
public Board createFromParcel(Parcel in) {
return new Board(in);
}
#Override
public Board[] newArray(int size) {
return new Board[size];
}
};
}
The Cell class.
public class Cell implements Parcelable {
private int row;
private int col;
private int value;
public Cell(int row, int col, int value) {
this.row = row;
this.col = col;
this.value = value;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
protected Cell(Parcel in) {
row = in.readInt();
col = in.readInt();
value = in.readInt();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(row);
dest.writeInt(col);
dest.writeInt(value);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Cell> CREATOR = new Parcelable.Creator<Cell>() {
#Override
public Cell createFromParcel(Parcel in) {
return new Cell(in);
}
#Override
public Cell[] newArray(int size) {
return new Cell[size];
}
};
}
Here is where the board is generated and passed to the game activity.
public class SudokuGenerator implements Response.ErrorListener, Response.Listener<JSONObject> {
private static final String TAG = "SUDOKU_GENERATOR";
private String url = "https://sugoku.herokuapp.com/board?difficulty=";
public int[][] puzzle = new int[9][9];
ArrayList<Cell> generatedPuzzleCells = new ArrayList<>();
private RequestQueue requestQueue;
private Context context;
LoadingDialog loadingDialog;
NewGameErrorDialog newGameErrorDialog;
public SudokuGenerator(Context context) {
requestQueue = Volley.newRequestQueue(context);
this.context = context;
this.loadingDialog = new LoadingDialog((Activity) context);
this.newGameErrorDialog = new NewGameErrorDialog((Activity) context);
}
public int[][] getPuzzle() {
return puzzle;
}
public void setPuzzle(int[][] puzzle) {
this.puzzle = puzzle;
}
public void setDifficulty(int difficulty) {
switch (difficulty){
case Globals.EASY:
url = url.concat("easy");
break;
case Globals.MEDIUM:
url = url.concat("medium");
break;
case Globals.HARD:
url = url.concat("hard");
break;
default:
url = url.concat("random");
break;
}
}
public void puzzleGenerator (int difficulty) {
loadingDialog.startLoadingDialog();
setDifficulty(difficulty);
System.out.println("Set Difficulty");
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url,null,this, this);
requestQueue.add(request);
System.out.println("Made request");
url = "https://sugoku.herokuapp.com/board?difficulty=";
}
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("ERROR Response");
newGameErrorDialog.startErrorDialog();
loadingDialog.dismissDialog();
}
#Override
public void onResponse(JSONObject response) {
System.out.println("Response");
//Check if not empty
if (response.length() == 0){
} //Error Handling
try {
JSONArray board = response.getJSONArray("board");
System.out.println("Board " + board);
for (int i = 0; i < board.length(); i++) {
JSONArray box = board.getJSONArray(i);
for (int j = 0; j < box.length(); j++) {
int k = box.getInt(j);
Cell cell;
if (k == 0) {
cell = new Cell(i, j, k, 0);
} else {
cell = new Cell(i, j, k, 1);
}
Log.d(TAG, "onResponse: GENERATED CELL: " + i +" "+j+" : "+k+" "+cell.isStartingCell());
generatedPuzzleCells.add(cell);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
Board generatedBoard = new Board(generatedPuzzleCells);
generatedBoard.printBoard();
loadingDialog.dismissDialog();
Intent gameIntent = new Intent(context, GameActivity.class);
gameIntent.putExtra("Board", generatedBoard);
gameIntent.putExtra("new game",true);
context.startActivity(gameIntent);
}
}
Here are two screenshots of what happens on the first tap of the new game (how it should be) and what happens after going back to main activity (where the new game button is) and pressing the button again.
In mainThread of Activity my image handler and Exo player (for play music)
used. Nut in OS-9 (Nokia) Device Not Working properly imageHandler -> that is connected to Workhandler.
below the code: WorkHandler
public class WorkHandler extends android.os.HandlerThread {
private Handler workHandler = null;
private volatile List<WorkMessageProxy> messageProxyList;
public WorkHandler() {
super("WorkHandler", Process.THREAD_PRIORITY_BACKGROUND);
start();
workHandler = new Handler(getLooper()) {
#Override
public void handleMessage(Message msg) {
if (messageProxyList != null) {
for (WorkMessageProxy workMessageProxy : messageProxyList) {
Log.i("workHandler", "handleMessage: Message: " + msg.toString());
workMessageProxy.handleMessage(msg);
}
}
}
};
}
public void post(Runnable run) {
workHandler.post(run);
}
public void postAtFrontOfQueue(Runnable runnable) {
workHandler.postAtFrontOfQueue(runnable);
}
public void postDelayed(Runnable runnable, long delay) {
workHandler.postDelayed(runnable, delay);
}
public void postAtTime(Runnable runnable, long time) {
workHandler.postAtTime(runnable, time);
}
public void addMessageProxy(WorkMessageProxy proxy) {
initMessageProxyList();
messageProxyList.add(proxy);
}
public void removeMessageProxy(WorkMessageProxy proxy) {
initMessageProxyList();
messageProxyList.remove(proxy);
}
private void initMessageProxyList() {
if (messageProxyList == null) {
messageProxyList = new ArrayList<>();
}
}
public Handler getHandler() {
return workHandler;
}
public interface WorkMessageProxy {
void handleMessage(Message msg);
}
}
ImageHandler
public class ImageFrameHandler implements WorkHandler.WorkMessageProxy {
private static final String TAG = "ImageFrameHandler";
private Resources resources;
private int[] resArray;
private int width;
private int height;
public boolean isRunning;
public final WorkHandler workHandler;
private File[] files;
private static final int FILE = 0;
private static final int RES = 1;
private int type;
private boolean isOpenCache;
#Retention(RetentionPolicy.SOURCE)
#IntDef({FILE, RES})
public #interface Operation {
}
ImageFrameHandler(#Operation int type) {
this.type = type;
imageCache = new ImageCache();
workHandler = new WorkHandler();
}
#Deprecated
public ImageFrameHandler() {
imageCache = new ImageCache();
workHandler = new WorkHandler();
}
private ImageCache imageCache;
private Handler handler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
if (onImageLoadListener != null) {
onImageLoadListener.onImageLoad(bitmapDrawable);
}
switch (msg.what) {
case RES:
load((int[]) msg.obj);
break;
case FILE:
load((File[]) msg.obj);
break;
}
}
};
private volatile float frameTime;
private volatile float delayTime;//in millisecond
private volatile int index = 0;
private volatile BitmapDrawable bitmapDrawable;
private OnImageLoadListener onImageLoadListener;
private boolean loop;
/**
* load frame form file directory;
*
* #param width request width
* #param height request height
* #param fileDir file directory
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(final String fileDir, int width, int height, int fps,
OnImageLoadListener onPlayFinish) {
if (!isRunning) {
isRunning = true;
this.width = width;
this.height = height;
loadImage(fileDir, fps, onPlayFinish);
}
}
/**
* load frame form file directory;
*
* #param fileDir file directory
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(final String fileDir, int fps, OnImageLoadListener onPlayFinish) {
if (!isRunning && !TextUtils.isEmpty(fileDir) && fps > 0) {
isRunning = true;
File dir = new File(fileDir);
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
loadImage(files, width, height, fps, onPlayFinish);
}
}
}
/**
* load frame form file files Array;
*
* #param width request width
* #param height request height
* #param files files Array
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(final File[] files, int width, int height, int fps,
OnImageLoadListener onPlayFinish) {
if (!isRunning) {
setImageFrame(files, width, height, fps, onPlayFinish);
load(files);
}
}
/**
* load frame form file files Array;
*
* #param files files Array
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(final File[] files, int fps, OnImageLoadListener onPlayFinish) {
loadImage(files, width, height, fps, onPlayFinish);
}
private void setImageFrame(final File[] files, int width, int height, float fps,
OnImageLoadListener onPlayFinish) {
this.width = width;
this.height = height;
if (imageCache == null) {
imageCache = new ImageCache();
}
this.onImageLoadListener = onPlayFinish;
frameTime = 1000f / fps + 0.5f;
workHandler.addMessageProxy(this);
this.files = files;
}
/**
* load frame form file resources Array;
*
* #param resArray resources Array
* #param width request width
* #param height request height
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(Resources resources, #RawRes int[] resArray, int width, int height, int fps,
OnImageLoadListener onPlayFinish) {
loadImage(resources, resArray, width, height, fps, onPlayFinish);
}
private void setImageFrame(Resources resources, #RawRes int[] resArray, int width, int height,
float fps,
OnImageLoadListener onPlayFinish) {
this.width = width;
this.height = height;
this.resources = resources;
if (imageCache == null) {
imageCache = new ImageCache();
}
this.onImageLoadListener = onPlayFinish;
frameTime = 1000f / fps + 0.5f;
workHandler.addMessageProxy(this);
this.resArray = resArray;
}
/**
* load frame form file resources Array;
*
* #param resArray resources Array
* #param fps The number of broadcast images per second
* #param onPlayFinish finish callback
*/
#Deprecated
public void loadImage(Resources resources, #RawRes int[] resArray, int fps,
OnImageLoadListener onPlayFinish) {
if (!isRunning) {
setImageFrame(resources, resArray, width, height, fps, onPlayFinish);
load(resArray);
}
}
/**
* loop play frame
*
* #param loop true is loop
*/
public ImageFrameHandler setLoop(boolean loop) {
if (!isRunning) {
this.loop = loop;
}
return this;
}
/**
* stop play frame
*/
public void stop() {
workHandler.getHandler().removeCallbacksAndMessages(null);
workHandler.removeMessageProxy(this);
handler.removeCallbacksAndMessages(null);
resources = null;
isRunning = false;
if (onImageLoadListener != null) {
onImageLoadListener.onPlayStop();
}
}
public void pause() {
isRunning = false;
workHandler.getHandler().removeCallbacksAndMessages(null);
// workHandler.removeMessageProxy(this);
handler.removeCallbacksAndMessages(null);
}
public void start() {
if (!isRunning) {
isRunning = true;
switch (type) {
case FILE:
load(files);
break;
case RES:
load(resArray);
break;
}
}
}
private void load(final File[] files) {
Log.i(TAG, "load: files");
Message message = Message.obtain();
message.obj = files;
message.what = FILE;
workHandler.getHandler().sendMessage(message);
workHandler.postDelayed(this::start, 10000);
}
private void load(#RawRes int[] res) {
Message message = Message.obtain();
message.obj = res;
message.what = RES;
workHandler.getHandler().sendMessage(message);
}
private void loadInThreadFromFile(final File[] files) {
Log.i(TAG, "loadInThreadFromFile: " + files.length);
Log.i(TAG, "loadInThreadFromFile: " + index);
if (index < files.length) {
File file = files[index];
//Log.i(TAG, "loadInThreadFromFile: " + file != null ? file.getAbsolutePath() : "");
if (file.isFile() && file.exists() && isPicture(file)) {
if (bitmapDrawable != null) {
imageCache.mReusableBitmaps.add(new SoftReference<>(bitmapDrawable.getBitmap()));
}
long start = System.currentTimeMillis();
bitmapDrawable = BitmapLoadUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), width, height, imageCache, isOpenCache);
long end = System.currentTimeMillis();
long diff = end - start;
//Log.i(TAG, "loadInThreadFromFile: frameTime: " + frameTime + "\tdelayTime: " + delayTime + "\tdiff=" + diff);
//Log.i(TAG, "loadInThreadFromFile: mod:" + ANIMATED_FRAME + "~" + Math.round(ANIMATED_FRAME));
float time = 0;
Log.i(TAG, "loadInThreadFromFile: ANIMATED_FRAME: " + (index % Math.round(ANIMATED_FRAME)));
if (index % Math.round(ANIMATED_FRAME) != 0) {
time = frameTime;
} else {
Log.e(TAG, "Have delay #" + index);
time = delayTime;
}
float updateTime = (time - diff) > 0 ? (time - diff) : 0;
Message message = Message.obtain();
message.what = FILE;
message.obj = files;
handler.sendMessageAtTime(message, (int) (SystemClock.uptimeMillis() + updateTime));
//Log.i(TAG, "loadInThreadFromFile: updateTime:" + updateTime + "\tindex:" + index + "\tlength:" + files.length);
index++;
} else {
index++;
loadInThreadFromFile(files);
}
} else {
if (loop) {
Log.i(TAG, "loadInThreadFromFile: loop: IF");
index = 0;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
loadInThreadFromFile(files);
}
}, (long) delayTime);
} else {
Log.i(TAG, "loadInThreadFromFile: loop=> " + loop);
index++;
bitmapDrawable = null;
frameTime = 0;
if (onImageLoadListener != null) {
onImageLoadListener.onPlayFinish();
}
isRunning = false;
onImageLoadListener = null;
}
}
if (onImageLoadListener != null) {
Log.i(TAG, "loadInThreadFromFile: index: " + index);
onImageLoadListener.onIndexChange(index);
}
}
private void loadInThreadFromRes(final int[] resIds) {
if (index < resIds.length) {
int resId = resIds[index];
if (bitmapDrawable != null) {
imageCache.mReusableBitmaps.add(new SoftReference<>(bitmapDrawable.getBitmap()));
}
long start = System.currentTimeMillis();
bitmapDrawable = BitmapLoadUtils.decodeSampledBitmapFromRes(resources, resId, width, height, imageCache, isOpenCache);
long end = System.currentTimeMillis();
float updateTime = (frameTime - (end - start)) > 0 ? (frameTime - (end - start)) : 0;
Message message = Message.obtain();
message.what = RES;
message.obj = resIds;
handler.sendMessageAtTime(message, index == 0 ? 0 : (int) (SystemClock.uptimeMillis() + updateTime));
index++;
} else {
if (loop) {
index = 0;
loadInThreadFromRes(resIds);
} else {
index++;
bitmapDrawable = null;
frameTime = 0;
if (onImageLoadListener != null) {
onImageLoadListener.onPlayFinish();
}
isRunning = false;
onImageLoadListener = null;
}
}
}
private boolean isPicture(File file) {
return file.getName().endsWith("png") || file.getName().endsWith("jpg");
}
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case RES:
loadInThreadFromRes((int[]) msg.obj);
break;
case FILE:
Log.i("ImageFrameHandler", "msg.obj; " + msg.obj.toString());
loadInThreadFromFile((File[]) msg.obj);
break;
}
}
public void setFps(float fps) {
Log.e(TAG, "setFps: " + fps);
//frameTime = 1000f / fps + 0.5f;
frameTime = 1000f / fps;
}
/**
* #param dps seconds in Sec
*/
public void setDelays(float dps) {
Log.e(TAG, "setDelays: " + dps);
delayTime = dps * 1000.0f;
}
public void setOnImageLoaderListener(OnImageLoadListener onPlayFinish) {
this.onImageLoadListener = onPlayFinish;
}
public interface OnImageLoadListener {
void onImageLoad(BitmapDrawable drawable);
void onPlayStop();
void onPlayFinish();
void onIndexChange(int index);
}
public static class FileHandlerBuilder implements FrameBuild {
private int width;
private int height;
private float fps = 30;
private float delays = 2;
private File[] files;
private OnImageLoadListener onPlayFinish;
private ImageFrameHandler imageFrameHandler;
private int startIndex;
private int endIndex;
public FileHandlerBuilder(#NonNull File[] files) {
if (files.length == 0) {
throw new IllegalArgumentException("fileDir is not empty");
}
this.files = files;
createHandler();
}
public FileHandlerBuilder(#NonNull String fileDir) {
Log.i(TAG, "FileHandlerBuilder: fileDir");
if (TextUtils.isEmpty(fileDir)) {
throw new IllegalArgumentException("fileDir is not empty");
}
File dir = new File(fileDir);
if (dir.exists() && dir.isDirectory()) {
files = dir.listFiles();
}
createHandler();
}
#Override
public FrameBuild setLoop(boolean loop) {
imageFrameHandler.setLoop(loop);
return this;
}
#Override
public FrameBuild stop() {
imageFrameHandler.stop();
return this;
}
// Just change the length of the array
#Override
public FrameBuild setStartIndex(int startIndex) {
if (startIndex >= files.length) {
throw new IllegalArgumentException("startIndex is not big to files length");
}
this.startIndex = startIndex;
return this;
}
#Override
public FrameBuild setEndIndex(int endIndex) {
if (endIndex > files.length) {
throw new IllegalArgumentException("endIndex is not big to files length");
}
if (endIndex <= startIndex) {
throw new IllegalArgumentException("endIndex is not to small startIndex");
}
this.endIndex = endIndex;
return this;
}
#Override
public FrameBuild setWidth(int width) {
this.width = width;
return this;
}
#Override
public FrameBuild setHeight(int height) {
this.height = height;
return this;
}
#Override
public FrameBuild setFps(float fps) {
this.fps = fps;
imageFrameHandler.setFps(fps);
return this;
}
#Override
public FrameBuild setDelays(float dps) {
this.delays = dps;
imageFrameHandler.setDelays(dps);
return this;
}
#Override
public FrameBuild setOnImageLoaderListener(OnImageLoadListener onPlayFinish) {
this.onPlayFinish = onPlayFinish;
return this;
}
#Override
public FrameBuild openLruCache(boolean isOpenCache) {
imageFrameHandler.openLruCache(isOpenCache);
return this;
}
#Override
public ImageFrameHandler build() {
if (!imageFrameHandler.isRunning) {
clip();
imageFrameHandler.setImageFrame(files, width, height, fps, onPlayFinish);
}
return imageFrameHandler;
}
private void createHandler() {
if (imageFrameHandler == null) {
Log.i(TAG, "createHandler: ");
imageFrameHandler = new ImageFrameHandler(FILE);
}
}
#Override
public FrameBuild clip() {
if (startIndex >= 0 && endIndex > 0 && startIndex < endIndex) {
files = split(files, startIndex, endIndex);
}
return this;
}
File[] split(File[] resArray, int start, int end) {
File[] ints = new File[end - start];
int index = 0;
for (int i = start; i < end; i++) {
ints[index] = resArray[i];
index++;
}
return ints;
}
}
private void openLruCache(boolean isOpenCache) {
this.isOpenCache = isOpenCache;
}
/**
* Transform into build builder mode
* <p>
* Two kinds are file
* Resource
*/
public static class ResourceHandlerBuilder implements FrameBuild {
#NonNull
private final Resources resources;
private int width;
private int height;
private float fps = 30;
private int[] resArray;
private OnImageLoadListener onPlayFinish;
private ImageFrameHandler imageFrameHandler;
private int startIndex;
private int endIndex;
public ResourceHandlerBuilder(#NonNull Resources resources, #NonNull #RawRes int[] resArray) {
if (resArray.length == 0) {
throw new IllegalArgumentException("resArray is not empty");
}
this.resources = resources;
this.resArray = resArray;
createHandler();
}
#Override
public FrameBuild setLoop(boolean loop) {
imageFrameHandler.setLoop(loop);
return this;
}
#Override
public FrameBuild stop() {
imageFrameHandler.stop();
return this;
}
#Override
public FrameBuild setStartIndex(int startIndex) {
if (startIndex >= resArray.length) {
throw new IllegalArgumentException("startIndex is not to big resArray length");
}
this.startIndex = startIndex;
return this;
}
#Override
public FrameBuild setEndIndex(int endIndex) {
if (endIndex > resArray.length) {
throw new IllegalArgumentException("endIndex is not big to resArray length");
}
if (endIndex <= startIndex) {
throw new IllegalArgumentException("endIndex is not to small startIndex");
}
this.endIndex = endIndex;
return this;
}
#Override
public FrameBuild clip() {
if (startIndex >= 0 && endIndex > 0 && startIndex < endIndex) {
resArray = split(resArray, startIndex, endIndex);
}
return this;
}
#Override
public FrameBuild setWidth(int width) {
this.width = width;
return this;
}
#Override
public FrameBuild setHeight(int height) {
this.height = height;
return this;
}
#Override
public FrameBuild setFps(float fps) {
this.fps = fps;
imageFrameHandler.setFps(fps);// There is a double calculation here. I want a better way to support dynamic change later.
return this;
}
#Override
public FrameBuild setDelays(float dps) {
return null;
}
#Override
public FrameBuild openLruCache(boolean isOpenCache) {
imageFrameHandler.openLruCache(isOpenCache);
return this;
}
#Override
public FrameBuild setOnImageLoaderListener(OnImageLoadListener onPlayFinish) {
this.onPlayFinish = onPlayFinish;
return this;
}
#Override
public ImageFrameHandler build() {
if (!imageFrameHandler.isRunning) {
clip();
imageFrameHandler.setImageFrame(resources, resArray, width, height, fps,
onPlayFinish);
}
return imageFrameHandler;
}
private void createHandler() {
if (imageFrameHandler == null) {
imageFrameHandler = new ImageFrameHandler(RES);
}
}
int[] split(int[] resArray, int start, int end) {
int[] ints = new int[end - start];
int index = 0;
for (int i = start; i < end; i++) {
ints[index] = resArray[i];
index++;
}
return ints;
}
}
}
I have used both as below in Activity:
Exoplayer init:
private void prepareExoPlayerFromURL() {
Log.i(TAG, "prepareExoPlayerFromURL: musicFilePath: " + musicFilePath);
try {
if (!FileUtils.createValidFile(musicFilePath).exists()) {
Log.i(TAG, "[prepareExoPlayerFromURL] is not Valid File URL");
Snackbar.make(toolbar, R.string.err_failed_to_pick_audio, Snackbar.LENGTH_LONG).show();
onAudioRemove();
return;
}
if (exoPlayer != null) {
MediaSource mediaSource = audioSource.createMediaSource(Uri.fromFile(FileUtils.createValidFile(musicFilePath)));
ClippingMediaSource clippingMediaSource = new ClippingMediaSource(mediaSource, 0, (long) totalDurationInSec * 1000 * 1000);
exoPlayer.prepare(clippingMediaSource);
btnMute.setVisibility(View.VISIBLE);
if (exoPlayer.getVolume() > 0) {
btnMute.setImageResource(R.drawable.ic_unmute);
}
/* TODO Write Permission */
joinAudio();
}
} catch (Throwable e) {
e.printStackTrace();
}
//initMediaControls();
}
**Play Music **
private void playMusic() {
Log.i(TAG, "playMusic: isForeGround: " + isForeGround);
if (isForeGround && this.layLoad.getVisibility() != View.VISIBLE && this.errorView.getVisibility() != View.VISIBLE &&
this.exoPlayer != null && !this.exoPlayer.isLoading()) {
Log.i(TAG, "playMusic: TRUE");
exoPlayer.seekTo(0);
exoPlayer.setPlayWhenReady(true);
} else {
Log.i(TAG, "playMusic: exoPlayer is null");
}
}
ResetMusic When One time ImageHandler is completed:
private void resetMusic() {
Log.i(TAG, "resetMusic: " + musicFilePath);
if (isForeGround && this.layLoad.getVisibility() != View.VISIBLE && this.errorView.getVisibility() != View.VISIBLE &&
this.exoPlayer != null) {
Log.i(TAG, "resetMusic: getApplicationLooper: "+exoPlayer.getApplicationLooper().getThread().getName());
Log.i(TAG, "resetMusic: getPlaybackLooper: "+exoPlayer.getPlaybackLooper().getThread().getName());
Log.i(TAG, "resetMusic: TRUE");
exoPlayer.seekTo(0);
exoPlayer.setPlayWhenReady(true);
} else {
Log.i(TAG, "resetMusic: exoPlayer is null");
}
}
Image handler used in Acvitiy in onCreate() method
imageFrameHandler = new ImageFrameHandler.FileHandlerBuilder(SlideShowUtility.getTempDirPath(this))
// .setFps((slideShowUtility.getVideoImages().size() - selectedImages.size()) * 1.0f / (selectedImages.size() - 1) * 1.0f)
.setFps(frameRate)
.setDelays(seconds)
.setWidth((int) (mWidth * mulX))
.setHeight((int) (mHeight * mulY))
.setLoop(true)
.build();
->Warning has Arrived in ResetMusic method when Exo player reset at position 0.
I have edited the question as your suggestions but null pointer exception is caught.I used connectionRequest instead of multipartRequest since i dont need to upload(just need to read the value frm json). All my codes below, please have a look.
Edited: exception
java.lang.NullPointerException
at userclasses.StateMachine$16.readResponse(StateMachine.java:1834)
at com.codename1.io.ConnectionRequest.performOperation(ConnectionRequest.java:438)
at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:263)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
Code:
#Override
protected void beforeImgGallery(Form f) {
int iter = 0;
GridLayout gr = new GridLayout(1, 1);
Container grid = new Container(gr);
gr.setAutoFit(true);
grid.setScrollableY(true);
grid.addComponent(new InfiniteProgress());
f.addComponent(BorderLayout.CENTER, grid);
f.removeAllCommands();
f.setBackCommand(null);
createPictureCommand(grid);
}
private static boolean animating;
private Vector<Map<String, Object>> responsesgallery;
String galleryPhotoUrl;
private void createPictureCommand(final Container grid) {
ConnectionRequest mp = new ConnectionRequest(){
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser p = new JSONParser();
results = p.parse(new InputStreamReader(input));
responsesgallery = (Vector<Map<String, Object>>) results.get("data");
//i've kept this for loop in postResponse but same error
for (int i = 0; i < responsesgallery.size(); i++) {
//null pointer exception in this line
final Button btn = createImageButton(i, grid, imageList.getSize());
//if i simply create a btn like below, it works
// final Button btn = new Button((URLImage.createToStorage(placeholder, token, galleryPhotoUrl, URLImage.RESIZE_SCALE_TO_FILL)));
imageList.addImageId(i);
grid.addComponent(i, btn);
Hashtable hm = (Hashtable) responsesgallery.get(i);
String galleryImgId = (String) hm.get("news_id");
galleryPhotoUrl = (String) hm.get("photo");
}
}
};
mp.setUrl("http://capitaleyedevelopment.com/~admin/traffic/api/news/getLatestNews");
NetworkManager.getInstance().addToQueueAndWait(mp);
}
ImageList imageList;
Button createImageButton(final int imageId, final Container grid, final int offset) {
final Button btn = new Button(URLImage.createToStorage(placeholder, token, galleryPhotoUrl, URLImage.RESIZE_SCALE_TO_FILL));
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
imageList.setSelectedIndex(offset);
final Container viewerParent = new Container(new LayeredLayout());
ImageViewer viewer = new ImageViewer(imageList.getItemAt(offset));
viewerParent.addComponent(viewer);
Container parent = new Container(new BorderLayout());
viewerParent.addComponent(parent);
viewer.setImageList(imageList);
grid.getParent().replace(grid, viewerParent, CommonTransitions.createSlide(CommonTransitions.SLIDE_HORIZONTAL, false, 300));
Display.getInstance().getCurrent().setBackCommand(createBackCommand(viewerParent, grid));
}
});
return btn;
}
public static final String SERVER_URL = "http://capitaleyedevelopment.com/~admin/traffic/api/news/getLatestNews";
class ImageList implements ListModel<Image> {
private int selection;
private long[] imageIds;
private EncodedImage[] images;
private EventDispatcher listeners = new EventDispatcher();
public void addImageId(int id) {
long[] n = new long[imageIds.length + 1];
EncodedImage[] nImages = new EncodedImage[n.length];
System.arraycopy(imageIds, 0, n, 0, imageIds.length);
System.arraycopy(images, 0, nImages, 0, images.length);
n[imageIds.length] = id;
imageIds = n;
images = nImages;
listeners.fireDataChangeEvent(-1, DataChangedListener.ADDED);
}
public long getSelectedImageId() {
return imageIds[selection];
}
public ImageList(long[] images) {
this.imageIds = images;
this.images = new EncodedImage[images.length];
}
public Image getItemAt(final int index) {
if (images[index] == null) {
images[index] = placeholder;
Util.downloadUrlToStorageInBackground(IMAGE_URL_PREFIX + imageIds[index], "FullImage_" + imageIds[index], new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
images[index] = EncodedImage.create(Storage.getInstance().createInputStream("FullImage_" + imageIds[index]));
listeners.fireDataChangeEvent(index, DataChangedListener.CHANGED);
} catch (IOException err) {
err.printStackTrace();
}
}
});
}
return images[index];
}
public int getSize() {
return imageIds.length;
}
public int getSelectedIndex() {
return selection;
}
public void setSelectedIndex(int index) {
WebServiceProxy.getPhotoLikesAsync(imageIds[selection], new Callback<Integer>() {
public void onSucess(Integer value) {
}
public void onError(Object sender, Throwable err, int errorCode, String errorMessage) {
}
});
selection = index;
}
public void addDataChangedListener(DataChangedListener l) {
listeners.addListener(l);
}
public void removeDataChangedListener(DataChangedListener l) {
listeners.removeListener(l);
}
public void addSelectionListener(SelectionListener l) {
}
public void removeSelectionListener(SelectionListener l) {
}
public void addItem(Image item) {
}
public void removeItem(int index) {
}
}
In the Photo Share demo (that's on github) I demonstrate something pretty similar. I used a custom list model that fetches the images to the ImageViewer dynamically.
The interesting bit is this list model where the images are downloaded dynamically as needed:
class ImageList implements ListModel<Image> {
private int selection;
private long[] imageIds;
private EncodedImage[] images;
private EventDispatcher listeners = new EventDispatcher();
public void addImageId(long id) {
long[] n = new long[imageIds.length + 1];
EncodedImage[] nImages = new EncodedImage[n.length];
System.arraycopy(imageIds, 0, n, 0, imageIds.length);
System.arraycopy(images, 0, nImages, 0, images.length);
n[imageIds.length] = id;
imageIds = n;
images = nImages;
listeners.fireDataChangeEvent(-1, DataChangedListener.ADDED);
}
public long getSelectedImageId() {
return imageIds[selection];
}
public ImageList(long[] images) {
this.imageIds = images;
this.images = new EncodedImage[images.length];
}
public Image getItemAt(final int index) {
if(images[index] == null) {
images[index] = placeholder;
Util.downloadUrlToStorageInBackground(IMAGE_URL_PREFIX + imageIds[index], "FullImage_" + imageIds[index], new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
images[index] = EncodedImage.create(Storage.getInstance().createInputStream("FullImage_" + imageIds[index]));
listeners.fireDataChangeEvent(index, DataChangedListener.CHANGED);
} catch(IOException err) {
err.printStackTrace();
}
}
});
}
return images[index];
}
public int getSize() {
return imageIds.length;
}
public int getSelectedIndex() {
return selection;
}
public void setSelectedIndex(int index) {
WebServiceProxy.getPhotoLikesAsync(imageIds[selection], new Callback<Integer>() {
public void onSucess(Integer value) {
if(likeCount != null) {
likeCount.setText("" + value);
likeCount.getParent().revalidate();
}
}
public void onError(Object sender, Throwable err, int errorCode, String errorMessage) {
}
});
selection = index;
}
public void addDataChangedListener(DataChangedListener l) {
listeners.addListener(l);
}
public void removeDataChangedListener(DataChangedListener l) {
listeners.removeListener(l);
}
public void addSelectionListener(SelectionListener l) {
}
public void removeSelectionListener(SelectionListener l) {
}
public void addItem(Image item) {
}
public void removeItem(int index) {
}
}
Ok I will try to make this clear as possible. I hope it doesn't get flagged before I get an answer.
I am trying to serialize a class for saving which works just fine. But some of the variables are not getting loaded correctly. Here is the code:
I also marked out places where the code is working and not working.
EDIT: Simplified code a bit more.
Class im saving: (Simple version of it)
public class classToSave implements Serializable {
/**
*
*/
private static final long serialVersionUID = -5184436214950145051L;
public static List<classToSave> classtosavelist = new ArrayList<classToSave>();
public static classToSave one = new OtherClass1("1", 1, 1, null, Item.1, 1);
public static classToSave two = new OtherClass1("2", 1, 2, one , Item.2, 1);
public static classToSave three = new OtherClass2("3", 1, 4, two , Item.3, 2);
public boolean done = false; < WONT LOAD/SAVE
public int lvl = 0; < WONT LOAD/SAVE
transient protected String name; < OK
protected int Xpos; < OK
protected int Ypos; < OK
public Skill parent; < OK
protected Item item; < OK
public int extra = 0; < OK (This Works..)
public classToSave(String s, int x, int y, Skill parent, Item item, int cost) {
this.name = s;
this.Xpos = x;
this.Ypos = y;
if(parent != null) {
this.Xpos += parent.Xpos;
this.Ypos += parent.Ypos;
}
this.parent = parent;
this.item = item;
add(this, s);
}
private void add(classToSave classtosave, String name) {
boolean flag = true;
for(int i = 0; i < skills.size(); i++) {
if(classtosavelist.get(i).getName().equalsIgnoreCase(name)) {
flag = false;
}
}
if(flag) {
classtosavelist.add(classtosave);
}
}
public int needPoints() {
return 1 + extra;
}
public boolean Done(int points) {
if(points >= needPoints()) {
this.done = true;
}
return this.done;
}
public int getLevel() {
return this.lvl;
}
public int MAXLevel() {
return 1;
}
public void LevelUp() {
if(this.lvl < MAXLevel()) {
this.lvl++;
}
}
public void Reset() {
this.lvl = 0;
}
public Item getRenderItem() {
return this.item;
}
public String getName() {
return this.name;
}
public Skill getParent() {
return this.parent;
}
public boolean isCompleteDone() {
return (getLevel() == MAXLevel() && done);
}
Here is the save and load:
private ClassToSave classtosave;
private void save(String savename) {
if (externalStorageWriteable) {
try {
File file = new File(ctxt.getExternalFilesDir(null), savename);
FileOutputStream fos = new FileOutputStream(file, false);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(classtosave);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void load(String savename) throws ClassNotFoundException, StreamCorruptedException, IOException {
if (externalStorageAvailable) {
File file = new File(ctxt.getExternalFilesDir(null), savename);
FileInputStream fis = new FileInputStream(file);
ObjectInputStream is = new ObjectInputStream(fis);
ClassToSave classtosave = (ClassToSave) is.readObject();
for (int i=0; i < classtosave.classtosavelist.size(); i++) {
classtosave.classtosavelist.get(i).Done(classtosave.classtosavelist.get(i).needPoints()); < WORKS
classtosave.classtosavelist.get(i).isCompleteDone(); < DOENST WORK
classtosave.classtosavelist.get(i).getLevel(); < DOESNT WORK
if (classtosave.classtosavelist.get(i).done == true){ <DOESNT WORK
classtosave.classtosavelist.get(i).done = true;
classtosave.classtosavelist.get(i).LevelUp();
}
}
}
is.close();
}
Sorry if brackets are out of place. This code was butchered(Renamed and modified) to make it more readable.
But basically this code is used for a "Skill tree" and what it is supposed to do is save if said skill is complete or not.
If this needs fixed let me know. I can also provide more code as needed.
Your constructor misses the boolean and the int. It should be like this :
public classToSave(boolean done, int lvl, String s, int x, int y, Skill parent, Item
item, int cost) {
this.done = done;
this.lvl = lvl;
...
}
Well I have this class for a game I'm making, and I'm trying to save the ArrayList notes. When I logout, it properly print the size, for example if I have 5 notes, when I log out notes.getSize() would be 5, but when I log in, it gets reset back to nothing. Why isn't notes saving?
public class Notes implements Serializable {
private static final long serialVersionUID = -4947870743226160329L;
private ArrayList<Note> notes = new ArrayList<Note>(30);
public class Note implements Serializable {
private static final long serialVersionUID = -4589885080580317958L;
private int color = 0;
private String text = "";
public Note(int color, String text) {
this.setColor(color);
this.setText(text);
}
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setColor(int color) {
this.color = color;
}
public int getColor() {
return color;
}
}
private transient Player player;
public Notes(Player p) {
this.player = p;
}
public void addNote(String text) {
System.out.println("Note Text: "+text);
if (text.length() > 50) {
player.getPackets().sendGameMessage("You can only enter notes up to 50 characters!");
return;
}
if (notes.size() < 30) {
notes.add(new Note(0, text));
} else {
player.getPackets().sendGameMessage("You cannot add more then 30 notes!");
return;
}
int NoteId = notes.size() - 1;
player.getPackets().sendConfig(1439, NoteId);
player.getTemporaryAttributtes().put("selectedNote", NoteId);
refreshNotes(false);
}
public void addNote(String text, int color) {
notes.add(new Note(color, text));
}
public void loadNotes() {
player.getPackets().sendIComponentSettings(34, 9, 0, 30, 2621470);
player.getPackets().sendHideIComponent(34, 3, false);
player.getPackets().sendHideIComponent(34, 44, false);
player.getPackets().sendIComponentText(34, 13, "Loading notes<br>Please wait...");
player.getPackets().sendConfig(1439, -1);
refreshNotes(true);
}
public void refreshNotes(boolean sendStartConfigs) {
for (int i = 0; i < 30; i++) {
player.getPackets().sendGlobalString(149 + i, i < notes.size() ? notes.get(i).getText() : "");
}
if (sendStartConfigs) {
for (int i = 1430; i < 1450; i++)
player.getPackets().sendConfig(i, i);
}
player.getPackets().sendConfig(1440, getFirstTotalColorValue());
player.getPackets().sendConfig(1441, getSecondTotalColorValue());
}
public int intColorValue(int color, int noteId) {
return (int) (Math.pow(4, noteId) * color);
}
public int getFirstTotalColorValue() {
int Color = 0;
for (int i = 0; i < 15; i++) {
if (notes.size() > i)
Color += intColorValue(notes.get(i).getColor(), i);
}
return Color;
}
public int getSecondTotalColorValue() {
int color = 0;
for (int i = 0; i < 15; i++) {
if (notes.size() > (i + 16))
color += intColorValue(notes.get(i + 16).getColor(), i);
}
return color;
}
public void deleteSelectedNote() {
if ((int)player.getTemporaryAttributtes().get("selectedNote") > -1) {
int slot = (int) player.getTemporaryAttributtes().get("selectedNote");
notes.remove(slot);
player.getTemporaryAttributtes().put("selectedNote", -1);
player.getPackets().sendConfig(1439, -1);
refreshNotes(false);
}
}
public void clear() {
notes.clear();
refreshNotes(false);
}
public void editNote(String string, int index) {
notes.get(index).setText(string);
refreshNotes(false);
}
public void setColor(int color, int index) {
notes.get(index).setColor(color);
refreshNotes(false);
}
public void deleteNote(int slot) {
notes.remove(slot);
refreshNotes(false);
}
public void setNotes(ArrayList<Note> setNotes) {
notes = setNotes;
refreshNotes(false);
}
}
And here is the class I manage saving/loading in
public class SerializableFilesManager {
private static final String PATH = "data/characters/";
private static final String BACKUP_PATH = "data/charactersBackup/";
public synchronized static final boolean containsPlayer(String username) {
return new File(PATH + username + ".p").exists();
}
public synchronized static Player loadPlayer(String username) {
try {
return (Player) loadSerializedFile(new File(PATH + username + ".p"));
} catch (Throwable e) {
Logger.handle(e);
}
try {
Logger.log("SerializableFilesManager", "Recovering account: "
+ username);
return (Player) loadSerializedFile(new File(BACKUP_PATH + username
+ ".p"));
} catch (Throwable e) {
Logger.handle(e);
}
return null;
}
public static boolean createBackup(String username) {
try {
Utils.copyFile(new File(PATH + username + ".p"), new File(
BACKUP_PATH + username + ".p"));
return true;
} catch (Throwable e) {
Logger.handle(e);
return false;
}
}
public synchronized static void savePlayer(Player player) {
try {
storeSerializableClass(player, new File(PATH + player.getUsername()
+ ".p"));
} catch (ConcurrentModificationException e) {
//happens because saving and logging out same time
} catch (Throwable e) {
Logger.handle(e);
}
}
public static final Object loadSerializedFile(File f) throws IOException,
ClassNotFoundException {
if (!f.exists())
return null;
ObjectInputStream in = new ObjectInputStream(new FileInputStream(f));
Object object = in.readObject();
in.close();
return object;
}
public static final void storeSerializableClass(Serializable o, File f)
throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(o);
out.close();
}
private SerializableFilesManager() {
}
}
Do NOT mark Player as transient, cause you are saving it, transient will prevent if from
getting saved, and will bring player to the default value of null, when deserialized.
Have you made the player class serializable ?
Its the Entire object graph that gets serialized or none... the purpose of transient is to make a particular member to be left off during serialization so that, the process of serialization goes smoothly.
For example, Suppose in a game we want to keep the progress of the player and hours of play for that session, but not the starting and ending times. So the starting and ending time can be made transient.
you should save your ArrayList with:
FileOutputStream fos = null;
ObjectOutputStream out = null;
try {
fos = new FileOutputStream("filename",false);
out = new ObjectOutputStream(fos);
out.writeObject(notes);
out.close();
System.out.println("Object Persisted");
} catch (IOException ex) {
ex.printStackTrace();
}
and when you open your project, import you Arraylist with:
FileInputStream fos;
try {
fos = new FileInputStream("filename");
ObjectInputStream oos = new ObjectInputStream(fos);
notes=(ArrayList) oos.readObject();
fos.close();
{
catch {
}
Thats because your Player is transient...I've tried to demonstrate your logic on other example...when Player was set to private, serialization has been successful and all data has been loaded back. Otherwise, when transient, Player reference was null, it loads only other serialized fields like int. When theres only a transient Player as field in class, the NullPointerException occurs, but ArrayList has size > 0.