I am trying to implement a REST interface in android and I need a Thread in the background sending "I am alive" messages to an ip address. To do so I created a Thread Called RestPostThread that runs in the background while I do stuff in my UI thread.
The problem is that after sending the first message to the RestPostThread I can't quit the looper or send a different message to it with another IP or something.
Here are the code for both the UI and the RestPostThread:
public class MainActivity extends AppCompatActivity{
Handler workerThreadHandler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
final TextView text1 = (TextView) findViewById(R.id.text1);
final TextView text2 = (TextView) findViewById(R.id.text2);
setSupportActionBar(toolbar);
final RestPostThread RPT = new RestPostThread();
RPT.start();
while(workerThreadHandler == null ) {
workerThreadHandler = RPT.getThreadHandler();
}
Button buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStop.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
try {
workerThreadHandler.getLooper().quit();
}catch(Exception e){
text1.setText(e.getMessage());
text2.setText( "Exception!");
}
}
});
Button buttonSend = (Button) findViewById(R.id.buttonSend);
buttonSend.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
try {
text1.setText(new RestGet().execute(editText.getText().toString()).get());
text2.setText("everything went well!");
}catch(Exception e){
text1.setText(e.getMessage());
text2.setText( "Exception!");
}
}
});
}
And here is the code for the RestPostThread:
public class RestPostThread extends Thread {
public Handler mHandler;
#Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
Log.d("MYASDASDPOASODAPO", "dentro mensaje");
while (!msg.obj.equals(null)) {
try {
Thread.sleep(1000);
URL url = new URL(msg.obj.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
String input = "<Instruction><type>put_me_in</type><room>Room 1</room></Instruction>";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
// throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
String aux = new String();
while ((output = br.readLine()) != null) {
aux = aux + output;
}
conn.disconnect();
//return aux;
} catch(MalformedURLException e) {
e.printStackTrace();
//return null;
} catch(IOException e) {
e.printStackTrace();
//return null;
} catch(Exception e) {
}
}
Log.d("CLOSING MESSAGE", "Closing thread");
}
};
Looper.loop();
}
public Handler getThreadHandler() {
return this.mHandler;
}
Have a look at HandlerThread for dealing with a thread to handle just messages. Your Handler should not loop on a message like that, it won't work. It's the Looper's job to deal with new, incoming Message or Runnable objects sent to the Handler which is bound to the Looper.
Regardless, you should take a closer look at using a Loader to handle REST type APIs; or, explore a 3rd party library, such as retrofit, for dealing with REST.
I managed to solve the issue. The problem was that I was wrapping everything inside this:
while (!msg.obj.equals(null)) {}
I implemented handlers in both this thread and the UI thread and now I have communication back and forth between the both, my RestPostThread looks like this now:
public class RestPostThread extends Thread {
public Handler mHandler,uiHandler;
public RestPostThread(Handler handler) {
uiHandler = handler;
}
#Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
try {
//Thread.sleep(1000);
URL url = new URL(msg.obj.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
String input = "<Instruction><type>put_me_in</type><room>Room 1</room></Instruction>";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
// throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
String aux = new String();
while ((output = br.readLine()) != null) {
aux = aux + output;
}
conn.disconnect();
Message msg2 = uiHandler.obtainMessage();
msg2.obj = aux;
uiHandler.sendMessage(msg2);
}catch(MalformedURLException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(Exception e){
}
}
};
Looper.loop();
}
public Handler getThreadHandler() {
return this.mHandler;
}
}
And in my MainActivity I have this handler that allows me to "loop" (basically is just going back and forth between the RestPostThread and the UIThread) my Post message until I decide to stop from the MainActivity changing the boolean loop:
public Handler uiHandler = new Handler() {
public void handleMessage(Message inputMessage) {
Log.d("FROM UI THREAD",inputMessage.obj.toString());
if(loop) {
Message msg = workerThreadHandler.obtainMessage();
String url = "http://192.168.1.224:9000/xml/android_reply";
msg.obj = url;
workerThreadHandler.sendMessageDelayed(msg,1000);
}
}
};
Related
I am having a problem with creating a socket and sending messages from an android app to a raspberry pi. I used this example from the following site: http://android-er.blogspot.nl/2016/05/android-client-example-2-communicate.html , this to understand how sockets work. But while I use AsyncTask, I still get an android.os.NetworkOnMainThreadException. This is my MainActivity:
public class MainActivity extends AppCompatActivity {
EditText editTextAddress, editTextPort, editTextMsg;
Button buttonConnect, buttonDisconnect, buttonSend;
TextView textViewState, textViewRx;
ClientHandler clientHandler;
ClientThread clientThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText) findViewById(R.id.address);
editTextPort = (EditText) findViewById(R.id.port);
editTextMsg = (EditText) findViewById(R.id.msgtosend);
buttonConnect = (Button) findViewById(R.id.connect);
buttonDisconnect = (Button) findViewById(R.id.disconnect);
buttonSend = (Button)findViewById(R.id.send);
textViewState = (TextView)findViewById(R.id.state);
textViewRx = (TextView)findViewById(R.id.received);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonDisconnect.setOnClickListener(buttonDisConnectOnClickListener);
buttonSend.setOnClickListener(buttonSendOnClickListener);
clientHandler = new ClientHandler(this);
}
View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
MainActivity.this.startService(new Intent(MainActivity.this,
ClientThread.class));
clientThread = new ClientThread(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()),
clientHandler);
clientThread.execute();
buttonConnect.setEnabled(false);
buttonDisconnect.setEnabled(true);
buttonSend.setEnabled(true);
}
};
View.OnClickListener buttonDisConnectOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(clientThread != null){
clientThread.setRunning(false);
}
}
};
String msgToSend;
View.OnClickListener buttonSendOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(clientThread != null){
msgToSend = editTextMsg.getText().toString();
clientThread.txMsg(msgToSend);
}
}
};
private void updateState(String state){
textViewState.setText(state);
}
private void updateRxMsg(String rxmsg){
textViewRx.append(rxmsg + "\n");
}
private void clientEnd(){
clientThread = null;
textViewState.setText("clientEnd()");
buttonConnect.setEnabled(true);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
}
public static class ClientHandler extends Handler {
public static final int UPDATE_STATE = 0;
public static final int UPDATE_MSG = 1;
public static final int UPDATE_END = 2;
private MainActivity parent;
public ClientHandler(MainActivity parent) {
super();
this.parent = parent;
}
#Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_STATE:
parent.updateState((String)msg.obj);
break;
case UPDATE_MSG:
parent.updateRxMsg((String)msg.obj);
break;
case UPDATE_END:
parent.clientEnd();
break;
default:
super.handleMessage(msg);
}
}
}
}
This the ClientThread.java code:
public class ClientThread extends AsyncTask<Void, Void, Void>{
String dstAddress;
int dstPort;
private boolean running;
MainActivity.ClientHandler handler;
Socket socket;
PrintWriter printWriter;
BufferedReader bufferedReader;
public ClientThread(String addr, int port, MainActivity.ClientHandler handler) {
super();
dstAddress = addr;
dstPort = port;
this.handler = handler;
}
public void setRunning(boolean running){
this.running = running;
}
private void sendState(String state){
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_STATE, state));
}
public void txMsg(String msgToSend){
if(printWriter != null){
printWriter.println(msgToSend);
}
}
#Override
protected Void doInBackground(Void... arg0) {
System.out.println("In doinbackground");
sendState("connecting...");
running = true;
try {
socket = new Socket(dstAddress, dstPort);
sendState("connected");
OutputStream outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream, true);
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
while (running) {
//bufferedReader block the code
String line = bufferedReader.readLine();
if (line != null) {
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_MSG, line));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (printWriter != null) {
printWriter.close();
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
handler.sendEmptyMessage(MainActivity.ClientHandler.UPDATE_END);
return null;
}
}
This is the error I'm getting:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.zerocj.projectsocked, PID: 2415
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at com.example.zerocj.projectsocked.ClientThread.txMsg(ClientThread.java:47)
at com.example.zerocj.projectsocked.MainActivity$3.onClick(MainActivity.java:85)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22260)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
You're calling your txMsg() method from a click listener which runs on the UI thread. And this method seems to be writing to a Writer that wired up to a socket.
If your wanna exchange messages back and forth between background thread and UI thread, maybe a better idea that an AsyncTask would be a Thread with Looper and handlers to pass the messages along from one thread to the other.
Please check your stack trace. It says use strict mode in your code
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 8)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
// Where you get exception write that code inside this.
}
Thanks hope this help you.
I have a Async task like this in my app:
private class getUserSummary extends AsyncTask<String, String, JSONObject> {
private ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(DashboardActivity.this);
pDialog.setMessage("Getting sales summary...");
//pDialog.setTitle("Getting sales summary...");
pDialog.setIndeterminate(true);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected JSONObject doInBackground(String... strings) {
String JsonResponse = null;
String JsonDATA = "email=my email address";
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
ServiceUrl smf = new ServiceUrl();
URL url = new URL(smf.getUserSummaryUrl());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
// is output buffer writter
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//set headers and method
Writer writer = new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8"));
writer.write(JsonDATA);
// json data
writer.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode == 400) {
InputStream inputResponse = urlConnection.getErrorStream();
reader = new BufferedReader(new InputStreamReader(inputResponse));
StringBuffer errorBuffer = new StringBuffer();
String errorLine;
while ((errorLine = reader.readLine()) != null) {
errorBuffer.append(errorLine + "\n");
}
Log.i("Error text", errorBuffer.toString());
return new JSONObject(errorBuffer.toString());
}
//Log.i("Response code", String.valueOf(inputStream));
InputStream inputStream = urlConnection.getInputStream();
//input stream
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = reader.readLine()) != null)
buffer.append(inputLine + "\n");
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
JsonResponse = buffer.toString();
//response data
Log.i("RESPONSE", JsonResponse);
return new JSONObject(JsonResponse);
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("ERROR", "Error closing stream", e);
}
}
}
return null;
}
protected void onPostExecute(JSONObject result) {
pDialog.dismiss();
//post operation here
}
}
and calling this in onCreate() method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initCollapsingToolbar();
new getUserSummary().execute();
}
I am running this as soon as user login activity distroyed. that's why I need to call this on onCreate() method. But I am getting this error when the call this in onCreate() method
android.view.WindowLeaked: Activity softlogic.computers.softlogicsalesreward.DashboardActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{5329b90 V.E...... R......D 0,0-1002,348} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:603)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:326)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109)
at android.app.Dialog.show(Dialog.java:505)
at softlogic.computers.softlogicsalesreward.DashboardActivity$getUserSummary.onPreExecute(DashboardActivity.java:88)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:604)
at android.os.AsyncTask.execute(AsyncTask.java:551)
at softlogic.computers.softlogicsalesreward.DashboardActivity.onResume(DashboardActivity.java:65)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1287)
at android.app.Activity.performResume(Activity.java:7015)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4210)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4323)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3426)
at android.app.ActivityThread.access$1100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
is there any other event where I can call this? or what I am doing wrong?
Your asyncTask must be like this.After see your code it may possible that You may forgot some method of AsyncTask.Compare with this example to better understand.
This is complete example of asyncTask:
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
ProgressDialog progressDialog;
#Override
protected String doInBackground(String... params) {
publishProgress("Sleeping..."); // Calls onProgressUpdate()
try {
int time = Integer.parseInt(params[0])*1000;
Thread.sleep(time);
resp = "Slept for " + params[0] + " seconds";
} catch (InterruptedException e) {
e.printStackTrace();
resp = e.getMessage();
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
progressDialog.dismiss();
finalResult.setText(result);
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,
"ProgressDialog",
"Wait for "+time.getText().toString()+ " seconds");
}
#Override
protected void onProgressUpdate(String... text) {
finalResult.setText(text[0]);
}
}
call like this:
new AsyncTaskRunner (this).execute();
you can use thread policy for this. It's work great.
Just add two line below setcontent.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build();
StrictMode.setThreadPolicy(policy);
You Forget to call pDialog.dismiss();
in onPostExecute method of Async task
I'm working on an android Quiz app with connection to a server over a socket. On the client side (Android device) I check in a while loop the answers which are given by a server (Java server). The connection and the receiving of the answer all goes good. The problem is that in my class to check for answers there's a bug. To give more information I will include a part of the code here:
public void startClient(){
checkValue = new Thread(new Runnable(){
#Override
public void run() {
try
{
final int PORT = 4444;
final String HOST = "192.168.1.118";
Socket SOCK = new Socket(HOST, PORT);
Log.e("success", "You connected to: " + HOST);
quizClient = new QuizClient(SOCK);
//Send the groupname to the list
PrintWriter OUT = new PrintWriter(SOCK.getOutputStream());
OUT.println(groupName);
OUT.flush();
Thread X = new Thread(quizClient);
X.start();
connected = true;
}
catch(Exception X)
{
Log.e("connection error", "Error: ", X);
}
}
});
checkValue.start();
}
public void testvalue(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
while(true){
if(message != null && !message.matches("")){
Thread.sleep(1000);
Log.e("receive", message);
buffer = message;
message = "";
Message msg = new Message();
String textTochange = buffer;
msg.obj = textTochange;
mHandler.sendMessage(msg);
Thread.sleep(3000);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
//call setText here
//String[] myStringArray = new String[];
value.clear();
String[] items = text.split(";");
for (String item : items)
{
value.add(item);
Log.e("message", item);
//System.out.println("item = " + item);
}
if(value.get(0).equals("1")){
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText("");
question.setText(value.get(2));
rad1.setText(value.get(3));
rad2.setText(value.get(4));
rad3.setText(value.get(5));
rad4.setText(value.get(6));
questionGroup.setVisibility(View.VISIBLE);
sendAnswer.setVisibility(View.VISIBLE);
} else if (value.get(0).equals("2")){
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText("");
question.setText(value.get(2));
answer.setVisibility(View.VISIBLE);
sendAnswer.setVisibility(View.VISIBLE);
} else
{
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText(text);
}
}
};
#Override
protected void onStop()
{
if (connected == true){
try {
quizClient.DISCONNECT();
} catch (IOException e) {
e.printStackTrace();
}
}
if(checkValue != null)
{
checkValue.interrupt();
}
super.onStop();
closeApplication();
}
So I make a new instance of this class (where I actually check the incoming stream of data)
public class QuizClient implements Runnable {
//Globals
Socket SOCK;
Scanner INPUT;
Scanner SEND = new Scanner(System.in);
PrintWriter OUT;
public QuizClient(Socket X)
{
this.SOCK = X;
}
public void run()
{
try
{
try
{
INPUT = new Scanner(SOCK.getInputStream());
OUT = new PrintWriter(SOCK.getOutputStream());
OUT.flush();
CheckStream();
}
finally
{
SOCK.close();
}
}
catch(Exception X)
{
Log.e("error", "error: ", X);
}
}
public void DISCONNECT() throws IOException
{
OUT.println("DISCONNECT");
OUT.flush();
SOCK.close();
}
public void CheckStream()
{
while(true)
{
RECEIVE();
}
}
public void RECEIVE()
{
if(INPUT.hasNext())
{
String MESSAGE = INPUT.nextLine();
if(MESSAGE.contains("#?!"))
{
}
else
{
QuizActivity.message = MESSAGE;
Log.e("test", MESSAGE);
}
}
}
public void SEND(String X)
{
OUT.println(X);
OUT.flush();
}
}
So the bug persist I think in the following class:
public void testvalue(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
while(true){
if(message != null && !message.matches("")){
Thread.sleep(1000);
Log.e("receive", message);
buffer = message;
message = "";
What I do here is make a thread and check if the "message" is not equals at null. The message come from the other class:
public void RECEIVE()
{
if(INPUT.hasNext())
{
String MESSAGE = INPUT.nextLine();
if(MESSAGE.contains("#?!"))
{
}
else
{
QuizActivity.message = MESSAGE;
Now most of the time this works good but there are 2 problems. When I go out of the page it disconnect from the server (works) I go back on the page and connect again to the server but this time I don't get any values on the screen (receiving is okj but for one of the other reason it does not go good in my handler). Also get an indexoutofboundexception after a time:
question.setText(value.get(2));
A second problem occurs some time while the program runs. There are moments that I also don't get a value on my interface while it correctly receive the input.
So my guess is that my solution of the thread to read in the values is not the best way to handle it. So now I ask to people with more experience what I can do to make this work without major problems? You need to know the connection works and I get the value in my QuizClient class. So the problem need to be in my main class.
My oncreate class:
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
selectgroep = (Spinner) findViewById(R.id.groepen);
questionGroup = (RadioGroup) findViewById(R.id.QuestionGroup);
sendAnswer = (Button) findViewById(R.id.sendAnswer);
rad1 = (RadioButton) findViewById(R.id.radio0);
rad2 = (RadioButton) findViewById(R.id.radio1);
rad3 = (RadioButton) findViewById(R.id.radio2);
rad4 = (RadioButton) findViewById(R.id.radio3);
answer = (EditText) findViewById(R.id.textanswer);
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
try {
connect();
} catch (InterruptedException e) {
e.printStackTrace();
}
//Code na het drukken op de knop
startserver = (Button) findViewById(R.id.startserver);
startserver.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startClient();
getID();
testvalue();
}
});
sendAnswer.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Stuur antwoord door en sluit alles af
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
answer.setText("");
rad1.setChecked(true);
rad1.setText("");
rad2.setText("");
rad3.setText("");
rad4.setText("");
question.setText("Wachten op server ... ");
}
});
}
Thank you in advance,
Thomas Thooft
I want to put a text from a webpage to a textview on Android 3.0. I have this code:
public class Biografie extends Activity {
private TextView outtext;
private String HTML;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_biografie);
outtext= (TextView) findViewById(R.id.textview1);
try {
getHTML();
} catch (Exception e) {
e.printStackTrace();
}
outtext.setText("" + HTML);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.biografie, menu);
return true;
}
private void getHTML() throws ClientProtocolException, IOException
{
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://artistone.appone.nl/api/biografie.php?dataid=998"); //URL!
HttpResponse response = httpClient.execute(httpGet, localContext);
String result = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = null;
while ((line = reader.readLine()) != null) {
result += line + "\n";
HTML = result;
}
}
}
My TextView returns "null" instead of the text from the page. Please help me to fix this. Thanks in regard.
Change your code to:
while ((line = reader.readLine()) != null) {
result += line + "\n";
}
HTML = result;
and try this:
outtext.setText(Html.fromHtml(HTML));
And instead of performing network action in main thread i will suggest you to do this in separate thread using AsyncTask
The problem is that you are getting NetworkOnMainThreadException
That is because you are downloading network content on the Main Thread (Activity's Thread).
Instead you need to use a background thread to download that content, or use AsynchTask.
A simple code that should fix this issue:
final Handler handler = new Handler();
Thread thread = new Thread() {
public void run() {
try {
getHTML();
handler.post(new Runnable() {
#Override
public void run() {
outtext.setText("" + HTML);
}
});
} catch (Exception e) {
e.printStackTrace();
handler.post(new Runnable() {
#Override
public void run() {
outtext.setText(e.toString());
}
}
}
};
thread.start(); // I forgot to start the thread. sorry !
Instead of :
try {
getHTML();
} catch (Exception e) {
e.printStackTrace();
}
outtext.setText("" + HTML);
Also take a look at this tutorial about android threads : Tutorial
I am using a socket thread.
It takes about 5 to 10 seconds to receive a message after sending a request message.
during that time I want my main thread to show "Please wait" popup.
The process flow of the program looks something like this.
show Popup
create socket thread.
-> this will connect to server
send request message to server
receive message.
My problem is that the show popup does not show up,
until after the socket thread receives its message.
Can anybody tell me a workaround to this problem?
public class LoginActivity extends Activity {
.... <some coded>
public void onClickLogin(View view) {
Log.d(this.toString(), "onClickLogin");
showLoginLoadingPopup();
String login_id = ((EditText)findViewById(R.id.login_id)).getText().toString();
String login_pwd = ((EditText)findViewById(R.id.login_pwd)).getText().toString();
conn = new Connection(handler, 1, null);
conn.start();
conn.sendData(Connection.SSPH_USERCERT, new String[] {login_id, login_pwd});
}
}
public class Connection extends Thread implements ConnectionConstant {
private InetAddress serverAddr;
private int serverPort;
private Socket socket;
PrintWriter out;
BufferedReader in;
private Handler handler;
public Connection(Handler h, int type, ServerClass server) {
Log.d(this.toString(), "Conncetion");
setServerInfo(type, server);
handler = h;
try {
connect();
} catch (Exception e) {
Log.e(this.toString(), "Error", e);
}
}
public void run() {
Log.d(this.toString(), "run");
try {
queue();
disconnect();
} catch (Exception e) {
Log.i(this.toString(), "Information", e);
}
}
private void connect() throws Exception {
if (serverAddr != null)
Log.d(this.toString(), "connect " + serverAddr.getHostName() + "("
+ Integer.toString(serverPort) + ")");
else
Log.d(this.toString(), "connect ");
socket = new Socket(serverAddr, serverPort);
socket.setSoLinger(true, 3000);
// UTF-8
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.i(this.toString(), "Socket connected!");
}
private void queue() throws Exception {
Log.d(this.toString(), "queue");
while (true) {
String sRcv = null;
sRcv = receive();
if (sRcv.length() > 0)
parseData(sRcv);
Thread.sleep(500);
Thread.yield();
}
}
private void send(String str) throws IOException {
Log.d(this.toString(), "send");
if (!socket.isConnected())
return;
Log.i(this.toString(), "Send : " + str);
out.println(str);
}
private String receive() throws Exception {
Log.d(this.toString(), "receive");
if (!socket.isConnected())
return null;
StringBuilder sb = new StringBuilder();
String str = "";
while ((str = in.readLine()) != null) {
Log.i(this.toString(), "Receive : " + str);
sb.append(str + "\n");
}
return sb.toString();
}
}
Use AsyncTask:
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
// show dialog
}
#Override
protected Void doInBackground(Void... params) {
// connect to the server
}
#Override
protected void onPostExecute(Void result) {
// close dialog
}
};
task.execute();
onPreExecute(), onPostExecute() and onProgressUpdate() are invoked on UI thread.
doInBackground() is invoked on background thread.
More about AsyncTask: http://developer.android.com/reference/android/os/AsyncTask.html
dialog = ProgressDialog.show(this, "", "Loading",true);
Runnable myRun = new Runnable(){
public void run(){
//DO ALL NETWORKING
//FINALLY DO THIS
runOnUiThread(new Runnable() {
public void run() {
}
});
};
Thread T = new Thread(myRun);
T.start();