I am trying to troubleshoot an Android server/client set of software which appears to be logging vast amounts of logcat messages containing "Socket setup caught IOexception", so Im guessing its in a loop.
For troubleshooting purposes I installed the server and client on the same physical device and experience the same problem.
Reading the code I cant work out why this would be, I have added comments starting //STACKEXCHANGE where I see the three logcat messages getting logged. Could anyone give me some pointers, Im not a java programmer, just an enthusiastic techie trying to get this working..
The logcat logs the messages in the following order
ControlLooop starting
Socket setup caught IOexception
Socket Established
Socket Closing
controlLoopEnding
And here is the code for the client software.
package com.jrbowling.robotclient;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.util.Log;
import android.widget.ToggleButton;
import android.widget.SeekBar;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;
import android.widget.EditText;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.view.Window;
import android.view.WindowManager;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.view.View.OnTouchListener;
import android.view.MotionEvent;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import android.app.AlertDialog;
import android.content.DialogInterface;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import android.os.Handler;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class MainActivity extends Activity {
Thread vidThread = null;
Thread clientThread = null;
private Socket s;
private static final String TAG = "RobotClient";
//private ToggleButton tb;
private ImageButton forward_button;
private ImageButton reverse_button;
private ImageButton right_button;
private ImageButton left_button;
private SeekBar throttle;
private ImageView imageWindow;
private ImageView connectedLED;
private ImageView signalStrengthIndicator;
private Boolean stayConnected = false;
String vidURL = "";
private String robotIP = "";
String direction = "stop";
Integer speed = 100;
Boolean robotEnabled = true;
Boolean robotConnected = false;
private Handler GUIUpdateHandler = new Handler();
private Integer signalStrength = 0;
private SharedPreferences pref;
private long timeLastPress = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set fullscreeen, black
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
setActivityBackgroundColor(0xff000000);
Log.i(TAG, "Robot client started");
initGUIComponents();
//get Robot IP from user, kick off threads and GUI updater
showIPAlert();
}
#Override
protected void onDestroy() {
Log.d(TAG,"onDestroy() called");
stayConnected = false;
socketCleanup();
super.onDestroy();
}
//#Override
//protected void onPause() {
// Log.d(TAG,"onPause() called");
// stayConnected = false;
// socketCleanup();
// super.onDestroy();
// }
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onBackPressed() {
//on back button, prompt user to press it again within 2 seconds to exit
Toast onBackPressedToast = Toast.makeText(this, "Press again within 2 seconds to confirm exit", Toast.LENGTH_SHORT);
long currentTime = System.currentTimeMillis();
if (currentTime - timeLastPress > 2000) {
onBackPressedToast.show();
timeLastPress = currentTime;
} else {
onBackPressedToast.cancel();
super.onBackPressed();
}
}
private void initGUIComponents()
{
imageWindow = (ImageView) findViewById(R.id.imageView1);
connectedLED = (ImageView) findViewById(R.id.imageViewConnectStatus);
signalStrengthIndicator = (ImageView) findViewById(R.id.ImageViewSignalStrength);
forward_button = (ImageButton) findViewById(R.id.forwardButton);
reverse_button = (ImageButton) findViewById(R.id.reverseButton);
right_button = (ImageButton) findViewById(R.id.rightButton);
left_button = (ImageButton) findViewById(R.id.leftButton);
throttle = (SeekBar)findViewById(R.id.throttleSeekbar);
throttle.setProgress(75);
forward_button.setOnTouchListener(forwardButtonListener);
reverse_button.setOnTouchListener(reverseButtonListener);
right_button.setOnTouchListener(rightButtonListener);
left_button.setOnTouchListener(leftButtonListener);
}
private void showIPAlert() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Please enter robot IP address");
alert.setMessage("Example: 192.168.1.100");
final EditText input = new EditText(this);
alert.setView(input);
input.setText(loadIP().toString());
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
robotIP = input.getText().toString();
Log.i(TAG, "User entered IP " + robotIP);
saveIP(robotIP);
//Handler launches GUIUpdater every 1000 ms. Launch when user clicks ok.
updateGUI();
//start network thread
stayConnected = true;
//launch network thread
clientThread = new Thread(new ClientThread());
clientThread.start();
vidURL = "http://"+robotIP+":8082/shot.jpg";
vidLoop();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
appExit();
}
});
alert.show();
}
private void appExit()
{
Log.i(TAG, "Exit requested by user");
this.finish();
}
private OnTouchListener forwardButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "forward";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener reverseButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "reverse";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener rightButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "rotateRight";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener leftButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "rotateLeft";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
//save and retrieve IP address using the shared preferences framework
private void saveIP(String IP)
{
//set up shared preferences editor
pref = getApplicationContext().getSharedPreferences("RobotClient", 0);
Editor editor = pref.edit();
editor.putString("robotIP", IP);
editor.commit();
}
private String loadIP()
{
String result;
pref = getApplicationContext().getSharedPreferences("RobotClient", 0);
Editor editor = pref.edit();
result = pref.getString("robotIP", "10.20.30.43");
return result;
}
private void setActivityBackgroundColor(int color) {
//0xff00ff00 first two are transparency, then rgb
View view = this.getWindow().getDecorView();
view.setBackgroundColor(color);
}
//periodically run updater to set connection status and wifi signal strength from robot
private void updateGUI()
{
GUIUpdateHandler.postDelayed(GUIUpdater, 1000);
}
private Runnable GUIUpdater = new Runnable(){
public void run() {
//Periodically update GUI elements from sensor and other data
Log.d(TAG,"Connected is: " + robotConnected.toString());
//update connection status
if (robotConnected)
{
connectedLED.setImageResource(R.drawable.led_green);
//update the wifi signal strength indicator
if ((signalStrength == 5) || (signalStrength==4))
signalStrengthIndicator.setImageResource(R.drawable.wifi4);
if (signalStrength == 3)
signalStrengthIndicator.setImageResource(R.drawable.wifi3);
if (signalStrength == 2)
signalStrengthIndicator.setImageResource(R.drawable.wifi2);
if (signalStrength == 1)
signalStrengthIndicator.setImageResource(R.drawable.wifi1);
if (signalStrength == 0)
signalStrengthIndicator.setImageResource(R.drawable.wifi0);
}
else
{
connectedLED.setImageResource(R.drawable.led_red);
signalStrengthIndicator.setImageResource(R.drawable.wifi0);
}
if (stayConnected)
updateGUI();
}
};
public void setConnected(boolean connected) {
robotConnected = connected;
}
public void socketCleanup()
{
try {
Log.d("clientThread","Socket Closing");
if (s != null)
s.close();
setConnected(false);
} catch (IOException e) {
Log.d(TAG, "Client comm thread got IOException in socketCleanup().");
}
}
private void vidLoop() //started from GUI alert, then kept going with call me from asynctask
{
if (stayConnected)
{
ImageDownloader id = new ImageDownloader();
id.execute(vidURL);
}
}
//this very useful chunk of code is from http://www.peachpit.com/articles/article.aspx?p=1823692&seqNum=3
private class ImageDownloader extends AsyncTask<String, Integer, Bitmap>{
protected void onPreExecute(){
}
#Override
protected Bitmap doInBackground(String... params) {
//TODO Auto-generated method stub
try{
URL url = new URL(params[0]);
HttpURLConnection httpCon =
(HttpURLConnection)url.openConnection();
if(httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
return BitmapFactory.decodeStream(is);
}catch(Exception e){
Log.e("Image","Failed to load image",e);
}
return null;
}
protected void onProgressUpdate(Integer... params){
//Update a progress bar here, or ignore it, it's up to you
}
protected void onPostExecute(Bitmap img){
ImageView iv = (ImageView)findViewById(R.id.imageView1);
if(iv!=null && img !=null){
iv.setImageBitmap(img);
//start next image grab
vidLoop();
}
}
protected void onCancelled(){
}
}
class ClientThread implements Runnable {
private static final int SERVERPORT = 8082;
public void run() {
Log.d("clientThread","clientThread started");
setConnected(false);
while ((!Thread.currentThread().isInterrupted()) && stayConnected)
{
controlLoop();
}
//user requested disconnect
Log.d("clientThread","clientThread ending");
}
void controlLoop()
{
BufferedReader s_input = null;
PrintWriter s_output = null;
String inputString = null;
String outputString = null;
Boolean continueLoop = true;
Log.d("clientThread","controlLoop starting");
//protocol:
//Java boolean: enabled or disabled
//Directions: stop, rotateRight, rotateLeft, forward, reverse
//Client sends: robotEnabled,direction,servoPanValue
//Server replies: sensor1,sensor2...
continueLoop = true;
try {
InetAddress serverAddr = InetAddress.getByName(robotIP);
Socket s = new Socket();
//int timeout = 2000; // DEFAULT milliseconds
int timeout = 6000; // milliseconds
SocketAddress sockaddr = new InetSocketAddress(serverAddr, SERVERPORT);
s.connect(sockaddr, timeout);
s_input = new BufferedReader(new InputStreamReader(s.getInputStream()));
s_output = new PrintWriter(s.getOutputStream(), true);
} catch (UnknownHostException e1) {
e1.printStackTrace();
Log.d("clientThread","Got invalid IP string in client thread");
continueLoop = false;
} catch (IOException e) {
Log.d("clientThread","Socket setup caught IOexception");
continueLoop = false;
//STACKEXCHANGE - THIS SEEMS TO BE WHERE THE CODE REPEATEDLY LOOPS AROUND TRYING TO CONNECT**********************************************************************************************
}
//STACKEXCHANGE - Loop starts below again and then logging "controlloop ending"
Log.d("clientThread","Socket Established");
setConnected(true);
try {
while ((stayConnected) && (continueLoop)) {
speed = throttle.getProgress();
if (stayConnected)
outputString = robotEnabled.toString() + "," + direction.toString() + "," + speed.toString();
else
outputString = "quit";
s_output.println(outputString);
if (!s_output.checkError())
{
inputString = s_input.readLine();
if (inputString == null)
{
continueLoop = false;
Log.d("clientThread","Unexpected disconnection.");
}
else
{
Log.d("clientThread","Client got: " + inputString.toString());
//parse returned string, which is just an integer containing the signal strength
try {
signalStrength = Integer.parseInt(inputString);
} catch(NumberFormatException nfe) {
Log.d(TAG,"Got invalid signal strength from client");
}
}
}
else
{
//printwriter.checkError returned true, something bad happened network-wise
continueLoop = false;
Log.d("clientThread","Printwriter.checkError() returned true, likely network problem");
}
}
socketCleanup();
Log.d("clientThread","controlLoop ending");
//STACKEXCHANGE - This is also logged in the catlog at the end of repetitive loop
} catch (IOException e) {
//this happens if the connection times out.
Log.d("clientThread", "Client comm thread got IOException in control loop.");
socketCleanup();
}
}//end control loop
} //end client thread
}
It's because you don't modify stayConnected.
You continually call
while ((!Thread.currentThread().isInterrupted()) && stayConnected)
{
controlLoop();
}
and get an exception each time with your call. Only modifying continueLoop to false. You should break your while on that condition or interrupt your thread as well for your intended behavior; or some other approach would work.
Related
This is my webserver working code on the pc:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Threading;
namespace Youtube_Manager
{
class WebServer
{
private readonly HttpListener _listener = new HttpListener();
private readonly Func<HttpListenerRequest, string> _responderMethod;
public WebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
{
if (!HttpListener.IsSupported)
throw new NotSupportedException(
"Needs Windows XP SP2, Server 2003 or later.");
// URI prefixes are required, for example
// "http://localhost:8080/index/".
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
// A responder method is required
if (method == null)
throw new ArgumentException("method");
foreach (string s in prefixes)
_listener.Prefixes.Add(s);
_responderMethod = method;
_listener.Start();
}
public WebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
: this(prefixes, method) { }
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("Webserver running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
string rstr = _responderMethod(ctx.Request);
byte[] buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch { } // suppress any exceptions
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch { } // suppress any exceptions
});
}
public void Stop()
{
_listener.Stop();
_listener.Close();
}
}
}
Then in form1 constructor:
WebServer ws = new WebServer(SendResponse, "http://+:8098/");//"http://localhost:8080/test/");
ws.Run();
And a method in form1:
public static string SendResponse(HttpListenerRequest request)
{
return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>", DateTime.Now);
}
And in the client side java code:
package com.test.webservertest;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.support.v7.app.ActionBarActivity;
import android.util.AndroidRuntimeException;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.content.Context;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EncodingUtils;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Locale;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.io.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
//import com.adilipman.webservertest.DebugServer;
public class MainActivity extends ActionBarActivity
{
private static final int MY_DATA_CHECK_CODE = 0;
public static MainActivity currentActivity;
TextToSpeech mTts;
private String targetURL;
private String urlParameters;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(new SingleTouchEventView(this, null));
currentActivity = this;
initTTS();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Dispatch onStart() to all fragments. Ensure any created loaders are
* now started.
*/
#Override
protected void onStart()
{
super.onStart();
TextToSpeechServer.main(null);
}
#Override
protected void onStop() {
super.onStop();
}
public void initTTS() {
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == MY_DATA_CHECK_CODE) {
if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
mTts = new TextToSpeech(getApplicationContext(), new OnInitListener() {
#Override
public void onInit(int i) {
if(i == TextToSpeech.SUCCESS) {
int result = mTts.setLanguage(Locale.US);
if(result == TextToSpeech.LANG_AVAILABLE
|| result == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
mTts.setPitch(1);
mTts.speak(textforthespeacch, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
});
} else {
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
public static String textforthespeacch = "";
public static void TextToSpeak(String text) {
textforthespeacch = text;
}
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private Path circlePath = new Path();
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
canvas.drawPath(circlePath, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
float lastdownx = 0;
float lastdowny = 0;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
circlePath.addCircle(eventX, eventY, 50, Path.Direction.CW);
lastdownx = eventX;
lastdowny = eventY;
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
byte[] response = Get(null);
if (response!=null)
Logger.getLogger("MainActivity(inside thread)").info(response.toString());
}
});
t.start();
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
circlePath.reset();
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
}
private byte[] Get(String urlIn)
{
URL url = null;
String urlStr="http://10.0.0.2:8098";
if (urlIn!=null)
urlStr=urlIn;
try
{
url = new URL(urlStr);
} catch (MalformedURLException e)
{
e.printStackTrace();
return null;
}
HttpURLConnection urlConnection = null;
try
{
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
byte[] buf=new byte[10*1024];
int szRead = in.read(buf);
byte[] bufOut;
if (szRead==10*1024)
{
throw new AndroidRuntimeException("the returned data is bigger than 10*1024.. we don't handle it..");
}
else
{
bufOut = Arrays.copyOf(buf, szRead);
}
return bufOut;
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
finally
{
if (urlConnection!=null)
urlConnection.disconnect();
}
}
}
First i'm running the server on the pc.
Then i'm running the program on the android when i make a touch on my smartphone the client connect to the server on the pc.
Now what i want to do is two things:
When connecting to the pc server do something. Once my device is connected to the pc server do something for example show a message like:
MessageBox.Show("connected");
2. After connected and if connected using a flag or something return a string to the client. I have on the pc a method called SendData i used it to send a string to a server on my android device:
private void SendDataToServer()
{
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("http://10.0.0.3:8080/?say=hello? im here ");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = "This is a test that posts this string to a Web server.";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
The question is if i need to use this method if i want to return something from my pc server to the client side ?
Since I finally figured out that the registerReceiver() method is usually running on the UI-Thread, I now want to change that. I just need some advice of how I could do that.
How would I be able to change registerReceiver() to stop freezing my app?
My doInBackground() method from the AsyncTask, runs another method that is using the registerReceiver(mReceiver, filter) method (both variables are already defined). But I want to keep seeing my ProgressDialog instead of making the app freezing.
I read about using a Handler and a new Thread, but I need some help there.
Thanks in advance.
Code:
package ch.scs.mod.tools.messagegenerator.business;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.telephony.SmsManager;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import ch.scs.mod.tools.messagegenerator.R;
import ch.scs.mod.tools.messagegenerator.model.Testcase;
import ch.scs.mod.tools.messagegenerator.model.Testset;
public class ReportActivity extends Activity implements OnClickListener {
private static final String TAG = "ReportActivity";
private TextView title;
private TextView lblReport;
private TextView lblEmail;
private TableLayout tblReport;
private Button btnBack;
private Testset testset;
private Testcase testcase;
private List<Testcase> testcases = new ArrayList<Testcase>();
private String number;
private String apn = "not used";
private String error;
private ArrayList<String> resultarray = new ArrayList<String>();
private ProgressDialog progressdialog;
private boolean running = false;
public enum State {
UNKNOWN, CONNECTED, NOT_CONNECTED
}
private ConnectivityManager mConnMgr;
private PowerManager.WakeLock mWakeLock;
private ConnectivityBroadcastReceiver mReceiver;
private NetworkInfo mNetworkInfo;
private State mState;
private boolean mListening;
private boolean mSending;
private SendMms sendMms = SendMms.getInstance();
private MMSTest myTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.report);
title = (TextView) findViewById(R.id.lblTitle);
lblReport = (TextView) findViewById(R.id.lblReport);
lblEmail = (TextView) findViewById(R.id.lblMmsEmail);
tblReport = (TableLayout) findViewById(R.id.tblReport);
btnBack = (Button) findViewById(R.id.btnBack);
progressdialog = new ProgressDialog(this);
progressdialog.setTitle("Please wait...");
progressdialog.setMessage("Sending...");
progressdialog.setCancelable(false);
Typeface tf = Typeface.createFromAsset(getAssets(),
"fonts/TheSansB_TT4_App.ttf");
title.setTypeface(tf);
lblEmail.setTypeface(tf);
lblReport.setTypeface(tf);
btnBack.setTypeface(tf);
lblEmail.setText(Html
.fromHtml("<a href=\'mailto:mathias.hubacher#swisscom.com\'>mathias.hubacher#swisscom.com</a>"));
lblEmail.setMovementMethod(LinkMovementMethod.getInstance());
btnBack.setOnClickListener(this);
testset = (Testset) this.getIntent().getSerializableExtra("testset");
number = (String) this.getIntent().getStringExtra("number");
lblReport.setText(getResources().getString(R.string.reportText1) + " "
+ number + " " + getResources().getString(R.string.reportText2));
testcases = testset.getTestcases();
resultarray.clear();
// Creating Views for Asynctask
ScrollView sv = new ScrollView(this);
LinearLayout ll = new LinearLayout(this);
HorizontalScrollView hsv = new HorizontalScrollView(this);
sv.setLayoutParams(new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getHeight()/2));
sv.setVerticalScrollBarEnabled(true);
sv.setHorizontalScrollBarEnabled(true);
sv.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
hsv.setLayoutParams(new HorizontalScrollView.LayoutParams(HorizontalScrollView.LayoutParams.MATCH_PARENT, HorizontalScrollView.LayoutParams.MATCH_PARENT));
hsv.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
ll.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
ll.setOrientation(LinearLayout.VERTICAL);
for (Testcase testc : testcases) {
TableRow tr = new TableRow(this);
TextView tv = new TextView(this);
TextView tvok = new TextView(this);
TextView tverror = new TextView(this);
tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
tv.setText(testc.getName() + " ");
tv.setTextColor(getResources().getColor(R.color.white));
tr.addView(tv);
tvok.setText("Sending...");
tvok.setTextColor(getResources().getColor(R.color.white));
tverror.setText("");
tverror.setTextColor(getResources().getColor(R.color.orange));
tr.addView(tvok);
tr.addView(tverror);
ll.addView(tr);
testc.setTextView(tv);
testc.setTextViewOk(tvok);
testc.setTextViewError(tverror);
}
hsv.addView(ll);
sv.addView(hsv);
tblReport.addView(sv);
myTask = new MMSTest();
myTask.execute();
}
private void createSms(List<Testcase> tcs) {
for (Testcase testc : tcs) {
error = "";
if (!testc.isExecute()) {
resultarray.add(getResources().getString(R.string.notExe));
resultarray.add(error);
} else {
sendSms(number, testc);
if (testc.isSuccsess()) {
resultarray.add(getResources().getString(R.string.ok));
resultarray.add(error);
} else {
resultarray.add(getResources().getString(R.string.failed));
resultarray.add(error);
}
}
testc.setRunning(true);
myTask.onProgressUpdate(resultarray.get(resultarray.size()-2), resultarray.get(resultarray.size()-1));
}
}
private class MMSTest extends AsyncTask<String, String, ArrayList<String>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mReceiver = new ConnectivityBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mReceiver, filter);
// progressdialog.show();
}
#Override
protected ArrayList<String> doInBackground(String... params) {
if (testset.getType().equals("sms")) {
Log.v(TAG, "Testtype SMS");
createSms(testcases);
} else if (testset.getType().equals("mms")) {
Log.v(TAG, "Testtype MMS");
mListening = true;
mSending = false;
mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// mReceiver = new ConnectivityBroadcastReceiver();
apn = (String) ReportActivity.this.getIntent().getStringExtra("apn");
startMms();
} else {
lblReport.setText("Error Testset Type not valid");
}
return resultarray;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
for (Testcase testc : testcases) {
if (testc.getRunning()) {
TextView tvok = testc.getTextViewOk();
TextView tverror = testc.getTextViewError();
if (testc.isExecute()) {
if (testc.isSuccsess()) {
tvok.setText(values[0]);
tvok.setTextColor(getResources().getColor(R.color.green));
tverror.setText(values[1]);
tverror.setTextColor(getResources().getColor(R.color.orange));
}
else {
tvok.setText(values[0]);
tvok.setTextColor(getResources().getColor(R.color.red));
tverror.setText(values[1]);
tverror.setTextColor(getResources().getColor(R.color.white));
}
}
else {
tvok.setText(values[0]);
tvok.setTextColor(getResources().getColor(R.color.red));
tverror.setText(values[1]);
tverror.setTextColor(getResources().getColor(R.color.white));
}
testc.setRunning(false);
break;
}
}
}
#Override
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
// int r = 0;
// for (Testcase testc : testcases) {
// TextView tvok = testc.getTextViewOk();
// TextView tverror = testc.getTextViewError();
// if (testc.isExecute()) {
// if (testc.isSuccsess()) {
// tvok.setText(result.get(r));
// tvok.setTextColor(getResources().getColor(R.color.green));
// tverror.setText(result.get(r+1));
// tverror.setTextColor(getResources().getColor(R.color.orange));
// }
// else {
// tvok.setText(result.get(r));
// tvok.setTextColor(getResources().getColor(R.color.red));
// tverror.setText(result.get(r+1));
// tverror.setTextColor(getResources().getColor(R.color.white));
// }
// }
// else {
// tvok.setText(result.get(r));
// tvok.setTextColor(getResources().getColor(R.color.red));
// tverror.setText(result.get(r+1));
// tverror.setTextColor(getResources().getColor(R.color.white));
// }
// r = r + 2;
// }
// progressdialog.dismiss();
}
}
private void sendMms() {
int responseCode=0;
for (Testcase testc : testcases) {
error = "";
if (testc.isExecute()) {
File file = new File(Environment.getExternalStorageDirectory(), ".MODTest/" + testc.getContentFile());
if (file.exists()) {
if (file.length() > 300000) {
Log.v(TAG, "File Length="+ Long.toString(file.length()));
error=getResources().getString(R.string.warningFileSize);
}
responseCode = sendMms.startMms(testc.getSubject(), number, apn, testc.getContentFile(), testc.getContentType(), getApplicationContext());
Log.v(TAG,"Test: "+ testc.getName() + " / Response code: " + Integer.toString(responseCode));
if (responseCode == 200) {
testc.setSuccsess(true);
responseCode = 0;
} else {
testc.setSuccsess(false);
error =Integer.toString(responseCode);
}
} else {
testc.setSuccsess(false);
error =getResources().getString(R.string.errorNoFile);
}
if (testc.isSuccsess()) {
resultarray.add(getResources().getString(R.string.ok) + " ");
resultarray.add(error);
} else {
resultarray.add(getResources().getString(R.string.failed) + " ");
resultarray.add(error);
}
} else {
resultarray.add(getResources().getString(R.string.notExe));
resultarray.add(error);
}
testc.setRunning(true);
myTask.onProgressUpdate(resultarray.get(resultarray.size()-2), resultarray.get(resultarray.size()-1));
}
endMmsConnectivity();
mSending = false;
mListening = false;
}
public void startMms() {
for (Testcase tcs : testcases) {
testcase = tcs;
number = number + "/TYPE=PLMN";
// IntentFilter filter = new IntentFilter();
// filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
// registerReceiver(mReceiver, filter);
try {
// Ask to start the connection to the APN. Pulled from Android
// source code.
int result = beginMmsConnectivity();
Log.v(TAG, "Result= " + Integer.toString(result));
if (result != PhoneEx.APN_ALREADY_ACTIVE) {
Log.v(TAG, "Extending MMS connectivity returned " + result
+ " instead of APN_ALREADY_ACTIVE");
// Just wait for connectivity startup without
// any new request of APN switch.
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendSms(String nr, Testcase tc) {
if (!tc.getBody().equals("")) {
SmsManager sm = SmsManager.getDefault();
sm.getDefault().sendTextMessage(nr, null, tc.getBody(), null, null);
tc.setSuccsess(true);
} else {
tc.setSuccsess(false);
error = getResources().getString(R.string.errorEmptySms);
}
}
#Override
public void onClick(View v) {
if (v.equals(findViewById(R.id.btnBack))) { // Wenn Button zurück
// geklickt wird
Intent startMmsTest = new Intent(ReportActivity.this,
StartActivity.class);
startActivity(startMmsTest);
}
}
protected void endMmsConnectivity() {
// End the connectivity
try {
Log.v(TAG, "endMmsConnectivity");
if (mConnMgr != null) {
mConnMgr.stopUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE,
PhoneEx.FEATURE_ENABLE_MMS);
}
} finally {
releaseWakeLock();
}
}
protected int beginMmsConnectivity() throws IOException {
// Take a wake lock so we don't fall asleep before the message is
// downloaded.
createWakeLock();
int result = mConnMgr.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, PhoneEx.FEATURE_ENABLE_MMS);
Log.v(TAG, "beginMmsConnectivity: result=" + result);
switch (result) {
case PhoneEx.APN_ALREADY_ACTIVE:
case PhoneEx.APN_REQUEST_STARTED:
acquireWakeLock();
return result;
}
throw new IOException("Cannot establish MMS connectivity");
}
private synchronized void createWakeLock() {
// Create a new wake lock if we haven't made one yet.
if (mWakeLock == null) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MMS Connectivity");
mWakeLock.setReferenceCounted(false);
}
}
private void acquireWakeLock() {
// It's okay to double-acquire this because we are not using it
// in reference-counted mode.
mWakeLock.acquire();
}
private void releaseWakeLock() {
// Don't release the wake lock if it hasn't been created and acquired.
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int responseCode;
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)
|| mListening == false) {
Log.w(TAG, "onReceived() called with " + mState.toString()
+ " and " + intent);
return;
}
boolean noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity) {
mState = State.NOT_CONNECTED;
} else {
mState = State.CONNECTED;
}
mNetworkInfo = (NetworkInfo) intent
.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
// mOtherNetworkInfo = (NetworkInfo) intent
// .getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
// mReason =
// intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
// mIsFailover =
// intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER,
// false);
// Check availability of the mobile network.
if (mNetworkInfo == null) {
/**
* || (mNetworkInfo.getType() !=
* ConnectivityManager.TYPE_MOBILE)) {
*/
Log.v(TAG, " type is not TYPE_MOBILE_MMS, bail");
return;
}
if (!mNetworkInfo.isConnected()) {
Log.v(TAG, " TYPE_MOBILE_MMS not connected, bail");
return;
} else {
Log.v(TAG, "connected..");
if (mSending == false) {
mSending = true;
sendMms();
}
}
}
}
}
Move it to onProgressUpdate() method, or better , onPostExecute()/onPreExecuteMethod() depending on your need.
These methods run on UI thread and not on the new thread creetaed by the Asynctask
I am trying to recieve a string via RFCOMM in android
I am a newbie to android and please help me
I can send data
but receiving fails
Here is my code
Please help me
package com.example.btspp;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.UUID;
import java.util.regex.Pattern;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class Buttons extends Activity {
private BluetoothAdapter btAdaptor;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private static final UUID MY_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
Thread workerThread;
byte[] readBuffer;
int readBufferPosition;
int counter;
volatile boolean stopWorker;
public String addressToConnect;
public static StringBuilder readStr;
TextView tv;
int aa;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_buttons);
tv = (TextView) findViewById(R.id.textView1);
addressToConnect = getIntent().getStringExtra("addressToConnect");
connectToDevice(addressToConnect);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
sendData("H");
// Toast.makeText(getBaseContext(), addressToConnect,
// Toast.LENGTH_SHORT).show();
}
});
}
private void sendData(String message) {
byte[] msgBuffer = message.getBytes();
try {
// final BT bt = new BT();
outStream.write(msgBuffer);
//readData();
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(getApplicationContext(),
"Not Sent BT Data : " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
/*private void readData(){
String instring = "";
try {
inStream = btSocket.getInputStream();
} catch (Exception e) {
// TODO: handle exception
}
Scanner scan = new Scanner(new InputStreamReader(inStream));
scan.useDelimiter(Pattern.compile("[\\r\\n]+"));
instring = scan.next();
scan = null;
Toast.makeText(getApplicationContext(),
"Got Data : " + instring, Toast.LENGTH_SHORT)
.show();
//return instring;
}*/
void beginListenForData()
{
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = inStream.available();
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
inStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable()
{
public void run()
{
tv.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
}
catch (IOException ex)
{
stopWorker = true;
}
}
}
});
workerThread.start();
}
private void connectToDevice(String address) {
btAdaptor = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = btAdaptor.getRemoteDevice(address);
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect();
outStream = btSocket.getOutputStream();
inStream = btSocket.getInputStream();
beginListenForData();
tv.setText("Bluetooth Opened");
//listenForMessages(btSocket, readStr);
// beginListenForData();
} catch (IOException e) {
// errorExit("Fatal Error",
// "In onResume() and socket create failed: " + e.getMessage() +
// ".");
Toast.makeText(getApplicationContext(),
"Not Connected : " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_buttons, menu);
return true;
}
}
I am a newbie to android and please help me
I can send data
but receiving fails
Here is my code
Please help me
Isn't 13 "\r" the usual delimiter and not 10?
So here's the deal. I'd like to implement the multiplayer Tic Tac Toe using Android. I deployed multithread server using Java, but I'm struggling with Client. As far as I know You should use background thread to handle the communication, and leave the UI thread just to UI stuff. I have some problems with developing the game loop and thread communication. I decided to use Handlers instead of AsyncTask.
I think that the loop should be implemented in background thread and look kinda like this:
Get the info from UI using Handler
Write the data to output stream to the server
Read the data from the input stream from the server
Process the data
Send the data to UI using other Handler.
I am testing this using Eclipse and emulators acting as a client. The problem is I just can't setup the handlers. One handler UIHandler is send as a parameter to the ClientThread Constructut, Net Handler is obtain through a method from Client thread into the UIThread.
I read that I need to use the Looper to process incoming data. Can't I just call the handleMessage method in an endless loop? I srsly don't know how to deploy this. I would be greatful for any ideas.
Main activity Client Class:
package com.example.tictactoecliet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.ViewFlipper;
public class MainActivity extends Activity implements OnClickListener,
ClientVocabulary {
private static final String TAG = MainActivity.class.getSimpleName();
private Socket client;
private PrintWriter pw;
private EditText etIp;
private TextView tvStatus;
private Button bCon;
private Socket socket;
PrintWriter out;
private BufferedReader in;
private RadioButton rbVsPlayer, rbVsAI;
private ViewFlipper vF;
private ClientThread cT;
private ImageButton[][] board = new ImageButton[5][5];
private Handler h, clientHandler;
SocketAddress sockaddr;
/******************************************************************************************/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
setupUIHandler();
try {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*****************************************
* initialize
*
* #return nothing ffs
******************************************/
private void init() {
etIp = (EditText) findViewById(R.id.etIP);
tvStatus = (TextView) findViewById(R.id.tvStatus);
rbVsAI = (RadioButton) findViewById(R.id.rbAI);
rbVsPlayer = (RadioButton) findViewById(R.id.rb2players);
bCon = (Button) findViewById(R.id.bCon);
//
// // listeners
//
vF = (ViewFlipper) findViewById(R.id.vF);
bCon.setOnClickListener(this);
board[0][0] = (ImageButton) findViewById(R.id.iB_1A);
board[0][1] = (ImageButton) findViewById(R.id.iB_2A);
board[0][2] = (ImageButton) findViewById(R.id.iB_3A);
board[0][3] = (ImageButton) findViewById(R.id.iB_4A);
board[0][4] = (ImageButton) findViewById(R.id.iB_5A);
board[1][0] = (ImageButton) findViewById(R.id.iB_1B);
board[1][1] = (ImageButton) findViewById(R.id.iB_2B);
board[1][2] = (ImageButton) findViewById(R.id.iB_3B);
board[1][3] = (ImageButton) findViewById(R.id.iB_4B);
board[1][4] = (ImageButton) findViewById(R.id.iB_5B);
board[2][0] = (ImageButton) findViewById(R.id.iB_1C);
board[2][1] = (ImageButton) findViewById(R.id.iB_2C);
board[2][2] = (ImageButton) findViewById(R.id.iB_3C);
board[2][3] = (ImageButton) findViewById(R.id.iB_4C);
board[2][4] = (ImageButton) findViewById(R.id.iB_5C);
board[3][0] = (ImageButton) findViewById(R.id.iB_1D);
board[3][1] = (ImageButton) findViewById(R.id.iB_2D);
board[3][2] = (ImageButton) findViewById(R.id.iB_3D);
board[3][3] = (ImageButton) findViewById(R.id.iB_4D);
board[3][4] = (ImageButton) findViewById(R.id.iB_5D);
board[4][0] = (ImageButton) findViewById(R.id.iB_1E);
board[4][1] = (ImageButton) findViewById(R.id.iB_2E);
board[4][2] = (ImageButton) findViewById(R.id.iB_3E);
board[4][3] = (ImageButton) findViewById(R.id.iB_4E);
board[4][4] = (ImageButton) findViewById(R.id.iB_5E);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setOnClickListener(this);
}// end of inner for
}// end of outer for
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case (R.id.bCon):
vF.showNext();
blockAllTile();
cT = new ClientThread((short) (rbVsPlayer.isChecked() ? 2:1), clientHandler, etIp.getText().toString());
cT.start();
break;
case (R.id.iB_1A):
sendLocation(0);
break;
case (R.id.iB_2A):
sendLocation(1);
break;
case (R.id.iB_3A):
sendLocation(2);
break;
case (R.id.iB_4A):
sendLocation(3);
break;
case (R.id.iB_5A):
sendLocation(4);
break;
case (R.id.iB_1B):
sendLocation(5);
break;
case (R.id.iB_2B):
sendLocation(6);
break;
case (R.id.iB_3B):
sendLocation(7);
break;
case (R.id.iB_4B):
sendLocation(8);
break;
case (R.id.iB_5B):
sendLocation(9);
break;
case (R.id.iB_1C):
sendLocation(10);
break;
case (R.id.iB_2C):
sendLocation(11);
break;
case (R.id.iB_3C):
sendLocation(12);
break;
case (R.id.iB_4C):
sendLocation(13);
break;
case (R.id.iB_5C):
sendLocation(14);
break;
case (R.id.iB_1D):
sendLocation(15);
break;
case (R.id.iB_2D):
sendLocation(16);
break;
case (R.id.iB_3D):
sendLocation(17);
break;
case (R.id.iB_4D):
sendLocation(18);
break;
case (R.id.iB_5D):
sendLocation(19);
break;
case (R.id.iB_1E):
sendLocation(20);
break;
case (R.id.iB_2E):
sendLocation(21);
break;
case (R.id.iB_3E):
sendLocation(22);
break;
case (R.id.iB_4E):
sendLocation(23);
break;
case (R.id.iB_5E):
sendLocation(24);
break;
}
}
public void unblockAllTile(){
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setEnabled(true);
}// end of inner for
}//
}
public void sendLocation(int location){
}
public void blockAllTile(){
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setEnabled(false);
}// end of inner for
}// end of outer for
}
private void setupUIHandler(){
h = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Bundle b = msg.getData();
String content = b.getString("msg");
if(content.equals(KKIP_ALL_CONNECTED)){
tvStatus.setText(KKIP_ALL_CONNECTED);
}else{
Log.i("i no noł", "i no noł");
}
}
};
}
}
Background Thread:
package com.example.tictactoecliet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class ClientThread extends Thread implements ClientVocabulary {
private Socket socket;
private short game_mode;
private Handler uiHandler;
private Handler netHandler;
private Bundle inMsgBundle, outMsgBundle;
private final static String TAG = ClientThread.class.getSimpleName();
private BufferedReader in;
private String ip, serverResponse;
PrintWriter out;
public ClientThread(Short game_mode, Handler h, String ip) {
this.game_mode = game_mode;
this.uiHandler = h;
this.ip = ip;
inMsgBundle = new Bundle();
outMsgBundle = new Bundle();
}
#Override
public void run() {
// TODO Auto-generated method stub
Log.i("Thread started",TAG);
connectionSetup();
Log.i("Setup connection",TAG);
Looper.prepare();
setupHandler();
Log.i("Handler set",TAG);
try {
play();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Looper.loop();
}// end of run
public Handler getHandlerToMsgQueue() {
while (netHandler == null) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return netHandler;
}
// //////////////////////////////////////////
public void connectionSetup() {
try {
Log.i("Setup start",TAG);
InetAddress serverAddress = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(serverAddress, 4321);
// socket = new Socket("192.168.0.102",4321);
socket = new Socket();
socket.connect(sockaddr);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
out.println(game_mode);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
Log.i("Setup finish",TAG);
} catch (Exception e) {
e.printStackTrace();
}
}
////////////////
public void setupHandler(){
Log.i("Handler ready",TAG);
netHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
notifyAll();
}
};
Log.i("Handler done",TAG);
}
///////////////////////////play//////////////////////////
public void play() throws Exception{
String response;
Log.v("Play start", "Play start");
try {
response =null;
if(in.readLine()!=null){
response=in.readLine();
Log.v(response, response);
}else{
Log.v(TAG, "Resposne is empty");
}
if( response.startsWith(KKIP_WELCOME)){
Log.i("wow welcome so much", "so much welcome");
char mark = response.charAt(8);
}else if (response.startsWith(KKIP_WAITING_FOR_OPPONENT)){
while (true){
//updatuj status zegarem, może wait i notify?
if(response.startsWith(KKIP_ALL_CONNECTED)){
Log.v("now we play","play");
sendMessageToUI(KKIP_ALL_CONNECTED);
response=in.readLine();
if(response.startsWith(KKIP_VALID_MOVE)){
//update board
}else if (response.startsWith(KKIP_MOVED)){
int loc = Integer.parseInt(response.substring(15));
//update board
}else if (response.startsWith(KKIP_VICTORY)){
}else if(response.startsWith(KKIP_DEFEAT)){
}else if (response.startsWith(KKIP_TIE)){
}
}
}//end of while (true)
//end of if connected
}
out.print(KKIP_QUIT);
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally{
socket.close();
}
}
private void sendMessageToUI(String msg){
Bundle data = new Bundle();
data.putString("msg", msg);
Message m = new Message();
m.setData(data);
uiHandler.sendMessage(m);
}
}
The code isn't finished yet, so some methods might seem strange. I am interested in solving the UIThread to BackGroundThread to Server Communication. Nothing else.
Handler objects are implicitly tied to the Looper running within the Thread in which they are created. Your background thread needs to create its own Looper (or use HandlerThread to take care of the Looper for you.) Then your background thread needs to communicate its Handler back to the main UI thread.
I'm trying to use a NIO server to read/write to a client for TCP connections. I've made a successful connection, and my initial message is sent to the server and correctly processed. It says that the server is sending a message back, but I'm not receiving any input on the client side. Also, after the server sends a message back, the application crashes saying that it was trying to read a null pointer (Line 127 server code).
It's important to note that I'm new to this concept and I don't really understand selectors. I've looked at tutorials, but contradictary messages have led me to be even more confused on the issue. If anyone has any good tutorials on this topic I'd be greatly appreciative.
Here's my code.
Client Main Activity Screen
package com.example.client;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.example.client.ServerService.Connect;
public class MainActivity extends Activity {
Button button;
TextView textView;
EditText editText;
EditText editTextps;
static Handler handler;
Connect connect=null;
Object myLock=new Object();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button1);
textView=(TextView) findViewById(R.id.textView1);
editText=(EditText) findViewById(R.id.editText1);
editTextps=(EditText) findViewById(R.id.editText2);
handler=new Handler(){
#Override
public void handleMessage(Message msg) { //Handle code for receiving messages
super.handleMessage(msg);//when a message is received it's input is processed here
Bundle bundle=msg.getData();
if(bundle.getInt("int") == 2){
if(bundle.getInt("valid") == 1){
Intent i = new Intent();
i.setClassName("com.example.client",
"com.example.client.ReadyScreen");
startActivity(i);
}else{
alertMessage();
editText.setText("");
editTextps.setText("");
}
}
}
};
startService(new Intent(getBaseContext(), ServerService.class));
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
String str=editText.getText().toString();
String strps=editTextps.getText().toString();
Message msg=Message.obtain();
Bundle bundle=new Bundle();
bundle.putString("name", str);
bundle.putString("password", strps);
msg.setData(bundle);
ServerService.threadHandler.sendMessage(msg);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void alertMessage() {
final android.app.AlertDialog.Builder show = new AlertDialog.Builder(this).setTitle("Error").setMessage("Wrong username/password").setNeutralButton("close", null);
show.show();
}
}
Server Service where I'm running the connection and IO
package com.example.client;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class ServerService extends Service {
Handler handler;
static MyHandle threadHandler;
Connect connect=null;
Object myLock=new Object();
static SocketChannel socketChannel=null;
public ByteBuffer sendBuffer=ByteBuffer.allocate(1024);
static ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);
static Selector selector;
private static final String TAG = ServerService.class.getSimpleName();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
Log.d(TAG, "Started running the service");
System.out.println(TAG + "Started running the service");
(new Thread(new ReceivingThread())).start();
(new Thread(new SendingThread())).start();
return START_STICKY;
}
#Override
public void onDestroy(){
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
class Connect {
SocketChannel socketChannel=null;
public ByteBuffer sendBuffer=ByteBuffer.allocate(1024);
ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);
Selector selector;
public Connect() {
try {
socketChannel=SocketChannel.open();
SocketAddress remoteAddress=new InetSocketAddress("192.168.2.17", 20001);
socketChannel.connect(remoteAddress);
socketChannel.configureBlocking(false);
selector=Selector.open();
socketChannel.register(selector, SelectionKey.OP_READ);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ReceivingThread implements Runnable{
#Override
public void run() {
Log.d(TAG, "Started running the receive thread");
connect=new Connect();
try {
while(true){
if(connect.selector.select()==0)
continue;
Play receivedMessage = new Play();
receivedMessage.play();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
public class SendingThread implements Runnable{
#Override
public void run() {
Log.d(TAG, "Started running the send thread");
Looper.prepare();
threadHandler=new MyHandle(Looper.myLooper());
Looper.loop();
}
}
class MyHandle extends Handler{
public MyHandle(){
}
public MyHandle(Looper looper){
super(looper);
}
public void handleMessage(Message msg){
String str=msg.getData().getString("name");
String strps=msg.getData().getString("password");
MyMessage message=new MyMessage();
message.setb((byte)1);
message.setUsername(str);
message.setPassword(strps);
try {
connect.sendBuffer.clear();
connect.sendBuffer.put(message.Message2Byte());
connect.sendBuffer.flip();
connect.socketChannel.write(connect.sendBuffer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The Server Code
package mytcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
public class NioServer {
/**
* #param args
*/
private int port = 20001;
final makeFlagFalse timerFlag = new makeFlagFalse();
static makeFlagFalse loginLoopBoolean = new makeFlagFalse();
private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
private static Map<SocketChannel, Integer> clientsMap = new HashMap<SocketChannel, Integer>();
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private Object gate = new Object();
public NioServer(int port) {
this.port = port;
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException, IOException {
final NioServer server = new NioServer(20001);
Thread accept = new Thread() {
public void run() {
server.accept();
}
};
accept.start();
while (loginLoopBoolean.flag == true)
server.loginService();
server.gamePlay(clientsMap);
}
public void init() throws IOException {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().setReuseAddress(true);
// serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
System.out.println("服务器启动");
}
public void accept() {
while (true) {
try {
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println("receive the connection from "
+ socketChannel.socket().getInetAddress() + ":"
+ socketChannel.socket().getPort());
socketChannel.configureBlocking(false);
synchronized (gate) {
selector.wakeup();
socketChannel.register(selector, SelectionKey.OP_READ);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println("Damn it");
}
}
}
public void loginService() throws InterruptedException {
synchronized (gate) {
}
try {
int n = selector.select();
if (n == 0){}
else{
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey key : selectionKeys) {
try {
if (key.isReadable()) {
handle_receive_login(key);
}
} catch (Exception e) {
try {
if (key != null) {
key.cancel();
key.channel().close();
}
} catch (Exception ex) {
e.printStackTrace();
}
}
}
selectionKeys.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void handle_receive_login(SelectionKey key) {
SocketChannel socketChannel = null;
ServerMessage message = null;
ServerMessage sendMessage = new ServerMessage();
socketChannel = (SocketChannel) key.channel();
rBuffer.clear();
try {
int count = socketChannel.read(rBuffer);
if (count > 0) {
rBuffer.flip();
message = ServerMessage.byte2Message(rBuffer.array());
System.out.println("Receive from"+ socketChannel.socket().getInetAddress() + " : "+ message.getb());
switch(message.getb()){
case(1):
int valid = DB.idCheck(message.getUsername(),
message.getPassword());
sendMessage.setb((byte) 2);
sendMessage.setValid(valid);
sendMes sendMes = new sendMes(sendMessage, socketChannel);
sendMes.send();
break;
case(2):
break;
case (3):
if(timerFlag.flag){
if(message.getReady() == 1){
if(clientsMap.size() < 6){
clientsMap.put(socketChannel, clientsMap.size() + 1);
sendMessage.setb((byte) 3);
sendMessage.setReady(1);
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}
else{
sendMessage.setb((byte) 3);
sendMessage.setReady(0);
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}
Timer timer = new Timer();
System.out.println("flag is " + timerFlag.flag);
TimerTask task = new TimerTask(){
public void run(){
timerFlag.falsify();
System.out.println("flag now is " + timerFlag.flag);
}
};
timer.schedule(task, 20*1000);
}
}else{
sendMessage.setb((byte) -1); /*-1 implies that game is currently in progress*/
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}
break;
case (4):
if(timerFlag.flag == true){
sendMessage.setb((byte) -2); /*send message saying "waiting for other players*/
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}else{
loginLoopBoolean.falsify();
}
break;
}
}/*end of if(count=0)*/
} catch (Exception e) {
e.printStackTrace();
key.cancel();
try {
socketChannel.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public void gamePlay(Map<SocketChannel, Integer> clientsMap) throws IOException, InterruptedException{
Dealer dealer = new Dealer();
dealer.createDeck();
ServerMessage sendMessage = new ServerMessage();
if(!clientsMap.isEmpty()){
Set<SocketChannel> clientSet = clientsMap.keySet();
Iterator<SocketChannel> iterator=clientSet.iterator();
SocketChannel currentPlayer;
while(iterator.hasNext()){
currentPlayer=iterator.next();
sendMessage.setb((byte) 4);
sendMessage.setCard1(dealer.dealCard(dealer.deck));
sendMessage.setCard2(dealer.dealCard(dealer.deck));
sendMes sendMes1 = new sendMes(sendMessage, currentPlayer);
sendMes1.send();
}
//send who's turn it is
loginService();
}
}
public static class makeFlagFalse{
boolean flag;
public makeFlagFalse() {
this.flag = true;
}
public void falsify(){
flag = false;
}
public void makeTrue(){
flag = true;
}
}
public class sendMes{
ServerMessage message;
SocketChannel currentPlayer;
sendMes(ServerMessage message,SocketChannel currentPlayer){
this.message = message;
this.currentPlayer=currentPlayer;
}
public void send() throws IOException{
sBuffer.clear();
sBuffer.put(message.Message2Byte());
sBuffer.flip();
currentPlayer.write(sBuffer);
}
}
}
I'm appreciative of any kind of help.
Thank you
private Object gate = new Object();
it should be volatile