I am creating a game where in the client I am supposed to get some arrays from a server and reveal them into the screen. I can press the button X times to get X arrays.
Currently I am using this code
rollDiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rollDice();
try {
int[] tempArray = new GetDiceTask().execute(socket).get();
printDice(tempArray,pDice);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
but if I don't like this array and I want another one I cannot use the AsyncTask cause I get the common error for Cannot execute task: the task has already been executed (a task can be executed only once).
This is my code for AsyncTask.
#Override
protected int[] doInBackground(Socket...params) {
Socket soc = params[0];
try {
ObjectInputStream ois = new ObjectInputStream(soc.getInputStream());
int[] tempArray = (int[]) (ois.readObject());
return tempArray;
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Is there a way that I can take multiple arrays without that exception?
Related
I'm currently learning about IO and Async but am having issues. I'm following a guide, and according to the guide this is supposed to work. I have created an activity with a simple EditText, TextView, and 2 Buttons(save and load). I am trying to have the save button take the text in the EditText and save to internal storage, and the load button take whatever is saved and set the TextView as that. Everything works flawlessly when I put all the code to run in the UI thread, but if I change the code to have the UI thread call the Async class for the loading, nothing seems to happen.
**Packages and imports have been removed to save space.
public class InternalData extends Activity implements OnClickListener {
EditText etSharedData;
TextView tvDataResults;
FileOutputStream fos;
String FILENAME = "InternalString";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sharedpreferences);
setupVariables();
}
private void setupVariables() {
Button bSave = (Button) findViewById(R.id.bSave);
Button bLoad = (Button) findViewById(R.id.bLoad);
etSharedData = (EditText) findViewById(R.id.etSharedPrefs);
tvDataResults = (TextView) findViewById(R.id.tvLoadSharedPrefs);
bSave.setOnClickListener(this);
bLoad.setOnClickListener(this);
try {
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bSave:
String sData = etSharedData.getText().toString();
try {
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(sData.getBytes());
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case R.id.bLoad:
String sCollected = null;
FileInputStream fis = null;
try {
fis = openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray) != -1){
sCollected = new String(dataArray);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try {
fis.close();
tvDataResults.setText(sCollected);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
}
}
The previous code makes everything work, but the UI lags a bit when trying to load large strings. When I try to have an LoadSomeStuff(Async) class do the loading, it does absolutely nothing when I hit Load on my phone. Within the LoadSomeStuff class it has the doInBackground method open the file and read the data into a string then return that string, and the onPostExecute method set the TextView's text to the returned String. Here's the code:
The onClick method for load button has:
new LoadSomeStuff().execute(FILENAME);
LoadSomeStuff Class *Note: This class is declared within the InternalData class.
public class LoadSomeStuff extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
String sCollected = null;
FileInputStream fis = null;
try {
fis = openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray) != -1){
sCollected = new String(dataArray);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try {
fis.close();
return sCollected;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(String result){
tvDataResults.setText(result);
}
}
}
Any help is greatly appreciated, thanks!
It actually looks like I had an extra method or two(like onPreExecute) with no code in them and when I deleted them it starting working.
My OutputStreamWrite refuses to append to my file. It only overwrites the first line constantly.
The String lightRowValues are sent from another method that goes through a table and gets one row at a time, sends that row data here, where that row is written to this file. Then the method loops back and gets the next row. SO I should have a list of rows but instead only have one line of the very last entry.
public static void appendToLtCSV(String lightRowValues, String CSVFinalFileName){
try {
csvfos = new FileOutputStream(CSVFinalFileName, true);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OutputStreamWriter sensorCSVWriter = new OutputStreamWriter(csvfos);
try {
sensorCSVWriter.append(lightRowValues);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
sensorCSVWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I have set the append flag to true and still the same problem....
I am using FTP to upload a file. This works great. This file contains information what the app should do.
So I am doing the following:
1) Download the file with Apache FTP Client (seems to work fine)
2) Try to read out the file with a BufferedReader and FileReader.
The problem:
I get a NullPointerException while reading the file. I guess that this is a timing problem.
The code has this structure:
...
getFile().execute();
BufferedReader br = new BufferedReader(...);
How can I solve this problem?
I have to use a seperate Thread (AsyncTask) to download the file because otherwise it will throw a NetworkOnMainThread Exception.
But how can I wait until the file is completely downloaded without freezing the UI?
I cannot use the BufferedReader inside AsyncTask because I use GUI elements and I have to run the interactions on the GUI Thread, but I have no access to it from AsyncTask. RunOnUiThread does not work as well because I am inside a BroadcastReceiver.
Some code:
private class GetTask extends AsyncTask{
public GetTask(){
}
#Override
protected Object doInBackground(Object... arg0) {
FTPClient client = new FTPClient();
try {
client.connect("*****");
}
catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
client.login("*****", "*****");
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream( "/sdcard/"+userID+".task" );
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
resultOk &= client.retrieveFile( userID+".task", fos );
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}/**
try {
client.deleteFile(userID+".task");
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
**/
try {
client.disconnect();
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
return null;
}
}
The Broadcastreceiver class:
public class LiveAction extends BroadcastReceiver {
...
private Context cont;
FileReader fr = null;
BufferedReader br;
#Override
public void onReceive(Context context, Intent intent)
{
cont = context;
...
new GetTask().execute();
try {
Thread.sleep(3000);
}
catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
fr = new FileReader("/sdcard/"+userID+".task");
}
catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
br = new BufferedReader(fr)
String strline = "";
try {
while ((strline = br.readLine()) != null){
if(strline.equals("taskone")){
//Some GUI Tasks
}
....
This is the relevant code.
I think the best approach would be to read the file's contents from the doInBackground inside the AsyncTask and then output an object which contains the info you need on the onPostExecute method of the async stask and then manipulate your UI.
private AsyncTask<String,Void,FileInfo> getFile(){
return new AsyncTask<String,Void,FileInfo>{
protected FileInfo doInBackground(String url){
FileInfo finfo = new FileInfo(); // FileInfo is a custom object that you need to define that has all the stuff that you need from the file you just downloaded
// Fill the custom file info object with the stuff you need from the file
return finfo;
}
protected void onPostExecute(FileInfo finfo) {
// Manipulate UI with contents of file info
}
};
}
getFile().execute();
Another option is to call another AsyncTask from onPostExecute that does the file parsing but I would not recommend it
I would try some thing like this:
private class GetTask extends AsyncTask{
LiveAction liveAction;
public GetTask(LiveAction liveAction){
this.liveAction = liveAction;
}
...
#Override
protected void onPostExecute(String result) {
liveAction.heyImDoneWithdownloading();
}
}
Ps: why the Thread.sleep(5000)?
public class LiveAction extends BroadcastReceiver {
...
public void heyImDoneWithdownloading(){
//all the things you want to do on the ui thread
}
}
My original goal is to build my own modal dialog. At some point, I have to run an inner loop, which would do really close to what GetMessage/PostMessage do in Win32, if you got Win32 experience then you are quite familiar with this. The inner loop will block current workflow but still process events. The pseudo code would be like,
private void doModal() {
doSth();
// start loop and process events
while (!isQuit) {
Message msg = nextMessage();
// process all wanted msgs, and simply discard all unexpected msgs
if (isWantedMsg) {
sendToTarget(msg);
}
}
}
I've looked into source code, Looper.loop(), which was,
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}
Basically I'd like to write such a loop, then I'm able to receive all msgs and process or drop them accordingly. Unfortunately, MessageQueue belongs to package android.os, I have no privilege to access most of its interfaces. Activity.dispatchTouchEvent is just a handler, not my case.
How could I do? Thanks.
==========================SOLUTION=====================================
I solved it by reflection, I exactly copied source of Looper.loop(), see below,
private void startModal() {
Class clsMsgQueue = null;
Method nextMethod = null;
Class clsMsg = null;
mQuitModal = false;
MessageQueue queue = Looper.myQueue();
clsMsgQueue = queue.getClass();
try {
nextMethod = clsMsgQueue.getDeclaredMethod("next", new Class[]{});
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
nextMethod.setAccessible(true);
while (!mQuitModal) {
Message msg = null;
try {
msg = (Message)nextMethod.invoke(queue, new Object[]{});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (msg != null) {
clsMsg = msg.getClass();
Field targetFiled = null;
try {
targetFiled = clsMsg.getDeclaredField("target");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
targetFiled.setAccessible(true);
Handler target = null;
try {
target = (Handler) targetFiled.get(msg);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (target == null) {
// No target is a magic identifier for the quit message.
mQuitModal = true;
}
target.dispatchMessage(msg);
msg.recycle();
}
}
}
When dialog was dismissed, mQuitModal was set to true either.
If don't care much about performance issue, it worked.
Sorry, Android deliberately does not support nested event loops like this. You just will have to structure your code a different way -- for dialogs you will typically start the dialog, return to the event loop, and implement callbacks to handle the result from it.
I need to send serialized Data from an Android Device to a Java Server.
I don't know why, but the communication seems to be very unstable. In the Debugger, the java.io.StreamCorruptedException: is thrown immediately after the start. not one Object is passing.
Without the debugger, nearly 10 Messages are passed until the same Exception is thrown.
Anyone got an idea, please help me:)
Thank you!
Fabian
Exception:
java.io.StreamCorruptedException: invalid type code: 2F
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at androidAnbindung.AndroidVerwalter.run(AndroidVerwalter.java:114)
java-code:
public void Nachrichtenaustausch(){
port ++;
try {
serverSocket = new java.net.ServerSocket(port);
System.out.println("Warte auf 2. Verbindungsaufbau...");
client = serverSocket.accept();
System.out.println("Verbindung 2 ist eingegangen...");
in = new ObjectInputStream(new ObjectInputStream(client.getInputStream()));
Nachricht n;
// starte den regulären Verkehr mit dem Androidgerät
new Thread(this).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
Nachricht speicher;
while (true) {
try {
speicher = (Nachricht) in.readObject();
if (speicher != null) {
System.out.println(speicher.getName()+"..............................."+speicher.getWerte().get(0));
}synchronized (objekliste) {
for (AndroidObject ao : this.objekliste) {
if (speicher.getName().equals(ao.name)) {
ao.abstrakter_Wert = speicher.getAktuellerWert();
if (speicher.getWerte()!=null) {
ao.werte = speicher.getWerte();
}
}
}
}
Thread.sleep(50);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception e) {
// TODO: handle exception
}
}
}
and the android thread:
#Override
public void run() {
// TODO Auto-generated method stub
try {
while (true) {
if (!nachrichtenliste.isEmpty()) {
Nachricht speicher = nachrichtenliste.get(0);
try {
out.writeObject(speicher);
out.flush();
synchronized (nachrichtenliste) {
nachrichtenliste.remove(speicher);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Thread.sleep(50);
handler.post(this);
}
} catch (Exception e) {
// TODO: handle exception
}
}
I can imagine that Android and Java are not exactly serialization compatible here. So that one side sends a code that the other does not expect.
I'd rather go with some more textual protocol (json, xml) here, than with serialization.