I'm making an app in which Bluetooth controls an Arduino car. I'm trying to get a switch to turn the motors ON and OFF (right now an LED), but when I run the app with the following code, it gets crashed.
if (on_off_switch.isChecked()) {
command = "1";
try {
outputStream.write(command.getBytes()); //transmits the value of command to the bluetooth module
} catch (IOException e) {
e.printStackTrace();
}
} else {
command = "10";
try {
outputStream.write(command.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
But when I run the app without that code section, it runs just fine. But when I run it with the code, the app doesn't get start and the Logcat says:
--------- beginning of crash
2018-11-10 14:22:36.570 3311-3311/com.example.btcar2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.btcar2, PID: 3311
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.btcar2/com.example.btcar2.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void java.io.OutputStream.write(byte[])' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2830)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2905)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:169)
at android.app.ActivityThread.main(ActivityThread.java:6595)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void java.io.OutputStream.write(byte[])' on a null object reference
at com.example.btcar2.MainActivity.onCreate(MainActivity.java:51)
at android.app.Activity.performCreate(Activity.java:7016)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2783)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2905)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:169)
at android.app.ActivityThread.main(ActivityThread.java:6595)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I don't know how to fix it. Please just write if you have a question that might help my situation, thanks.
Here is the rest of my code
public class MainActivity extends AppCompatActivity {
final String DEVICE_ADDRESS = "00:12:12:24:06:48"; //MAC Address of Bluetooth Module
private final UUID PORT_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private BluetoothDevice device;
private BluetoothSocket socket;
private OutputStream outputStream;
Button bluetooth_connect_btn;
String command; //string variable that will store value to be transmitted to the bluetooth module
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Switch on_off_switch = (Switch) findViewById(R.id.on_off_switch);
on_off_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.v("Switch State=", "" + isChecked);
}
});
if (on_off_switch.isChecked()) {
command = "1";
try {
outputStream.write(command.getBytes()); //transmits the value of command to the bluetooth module
} catch (IOException e) {
e.printStackTrace();
}
} else {
command = "10";
try {
outputStream.write(command.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
bluetooth_connect_btn = (Button) findViewById(R.id.bluetooth_connect_btn);
//Button that connects the device to the bluetooth module when pressed
bluetooth_connect_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (BTint()) {
BTconnect();
}
}
});
}
//Initializes bluetooth module
public boolean BTint() {
boolean found = false;
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) //Checks if the device supports bluetooth
Toast.makeText(getApplicationContext(), "Device doesn't support bluetooth", Toast.LENGTH_SHORT).show();
if (!bluetoothAdapter.isEnabled()) //Checks if bluetooth is enabled. If not, the program will ask permission from the user to enable it
{
Intent enableAdapter = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableAdapter, 0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
if (bondedDevices.isEmpty()) //Checks for paired bluetooth devices
Toast.makeText(getApplicationContext(), "Please pair the device first", Toast.LENGTH_SHORT).show();
else {
for (BluetoothDevice iterator : bondedDevices) {
if (iterator.getAddress().equals(DEVICE_ADDRESS)) {
device = iterator;
found = true;
break;
}
}
}
return found;
}
public boolean BTconnect() {
boolean connected = true;
try {
socket = device.createRfcommSocketToServiceRecord(PORT_UUID); //Creates a socket to handle the outgoing connection
socket.connect();
Toast.makeText(getApplicationContext(),
"Connection to bluetooth device successful", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
connected = false;
}
if (connected) {
try {
outputStream = socket.getOutputStream(); //gets the output stream of the socket
} catch (IOException e) {
e.printStackTrace();
}
}
return connected;
}
#Override
protected void onStart() {
super.onStart();
}
}
As Amjad Alwareh said, outputStream object is null. You can see that from this statement in Logcat:
java.lang.NullPointerException: Attempt to invoke virtual method 'void java.io.OutputStream.write(byte[])' on a null object reference
By putting this code
if (on_off_switch.isChecked()) {
command = "1";
try {
outputStream.write(command.getBytes()); //transmits the value of command to the bluetooth module
} catch (IOException e) {
e.printStackTrace();
}
} else {
command = "10";
try {
outputStream.write(command.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
in onCreate you are attempting to perform some actions with Bluetooth module without making sure that you have a connection.
I don't know your design and what are you trying to achieve. But I can suggest to put code above in a separate method like this:
private void performAction() {
if (on_off_switch.isChecked()) {
command = "1";
try {
outputStream.write(command.getBytes()); //transmits the value of command to the bluetooth module
} catch (IOException e) {
e.printStackTrace();
}
} else {
command = "10";
try {
outputStream.write(command.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
And then call it in BTconnect() if you want to make something right after connection is established:
// code before
if (connected) {
try {
outputStream = socket.getOutputStream(); //gets the output stream of the socket
performAction(); // call it here
} catch (IOException e) {
e.printStackTrace();
}
}
Or call this method in onCheckedChanged
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.v("Switch State=", "" + isChecked);
performAction(); // call it here
}
outputStream is null , You must create a new object of it , like what are you doing in BTconnect() outputStream = socket.getOutputStream();
Related
My app has a MainActivity.java which initializes 2 buttons (btnBTConnect and btnBTStop) and calls setOnClickListener methods for them.
In BluetoothActivity.java, I have the onClick methods which call the methods. For btnBTConnect it calls my methods to find the bluetooth device (findBT), connect to it and receive the inputStream (openBT). For btnBTStop, it calls my method to close the connection (closeBT).
When I click the start bluetooth button, I have no problem. The connection is made and data is received as expected (BluetoothSocket and InputStream are NOT null).
However, when I click the bluetooth Stop button, to stop the data and close the InputStream and Socket, I get a null object reference error.
Can someone please help? Is it because of how I have the onClick setup? By using switch and case, are all my variables from the findBT and openBT methods removed when it switches to the bluetooth stop case? Is that why my Bluetooth Socket and InputStream are null when I try to close them?
How can I fix this?
Thanks
MainAcitivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public Button btnBTConnect;
public Button btnBTStop;
BluetoothAdapter mBTAdap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBTAdap = BluetoothAdapter.getDefaultAdapter();
btnBTConnect = findViewById(R.id.btnBTConnect);
btnBTStop = findViewById(R.id.btnBTStop);
btnBTConnect.setOnClickListener(new BluetoothActivity(getApplicationContext()));
btnBTStop.setOnClickListener(new BluetoothActivity(getApplicationContext()));
}
BluetoothActivity
public class BluetoothActivity implements View.OnClickListener{
private static final String TAG = "BluetoothActivity";
Context mContext;
public BluetoothAdapter mBTAdap;
public BluetoothSocket mBTSock;
public BluetoothDevice mBTDev;
public InputStream mBTIP;
public Thread mBTThread;
byte[] mBuffer;
volatile boolean mStopThread;
public BluetoothActivity(Context myContext) {
this.mBTAdap = BluetoothAdapter.getDefaultAdapter();
this.mContext = myContext;
}
#Override
public void onClick(View mView) {
switch (mView.getId()){
case R.id.btnBTConnect:
try {
findBT();
openBT();
} catch (IOException e) {Log.e(TAG, "onClick: " + e.getMessage(), e);}
break;
case R.id.btnBTStop:
try {
closeBT();
} catch (IOException e) {Log.e(TAG, "onClick: " + e.getMessage(), e);}
break;
default:
break;
}
}
public void findBT() {
Set<BluetoothDevice> mBTPairedDevices = mBTAdap.getBondedDevices();
if (mBTPairedDevices.size() > 0) {
for (BluetoothDevice device : mBTPairedDevices) {
if (device.getName().equals("myDevice")) {
mBTDev = device;
toastMessage(mBTDev.getName() + " device found");
break;
} else {toastMessage("No device found");}
}
} else {toastMessage("No Devices paired");}
}
public void openBT() throws IOException
{
UUID mUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
mBTSock = mBTDev.createRfcommSocketToServiceRecord(mUUID);
} catch (IOException e) {
Log.e(TAG, "openBT: " + e.getMessage(), e); toastMessage("Couldn't create RFComm socket");}
mBTSock.connect();
mBTIP = mBTSock.getInputStream();
listenBT();
}
public void listenBT(){
mStopThread = false;
mBuffer = new byte[6];
mBTThread = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted() && !mStopThread) {
try {
bytes = mBTIP.read(mBuffer);
} catch (IOException e) {
mStopThread = true;
Log.e(TAG, "run: " + e.getMessage(), e);
}
}
}
}); mBTThread.start();
}
public void closeBT() throws IOException {
mStopThread = true;
mBTIP.close();
mBTSock.close();
toastMessage("BT Closed");
Log.d(TAG, "closeBT: BT Closed");
}
private void toastMessage(String message){
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
}
Logcat
02-06 19:54:41.256 3915-3915/com.example.mark.btconnflow E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mark.btconnflow, PID: 3915
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.BluetoothSocket.close()' on a null object reference
at com.example.mark.btconnflow.BluetoothActivity.closeBT(BluetoothActivity.java:202)
at com.example.mark.btconnflow.BluetoothActivity.onClick(BluetoothActivity.java:79)
at android.view.View.performClick(View.java:6261)
at android.widget.TextView.performClick(TextView.java:11159)
at android.view.View$PerformClick.run(View.java:23751)
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:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
You make two different objects and put them in listeners. Try with:
BluetoothActivity listener = new BluetoothActivity(getApplicationContext());
btnBTConnect.setOnClickListener(listener);
btnBTStop.setOnClickListener(listener);
I've been create an app for Bluetooth control.
Everything is fine until I open BluetoothServerSocket to listen to an incoming connection.
here is my code:
public class ListeningThread extends Thread {
private final BluetoothServerSocket bluetoothServerSocket;
public ListeningThread() {
BluetoothServerSocket temp = null;
try {
temp = myBluetoothAdapter.listenUsingRfcommWithServiceRecord(getString(R.string.app_name), uuid);
Toast.makeText(getApplicationContext(), "Listening",
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
bluetoothServerSocket = temp;
}
public void run() {
BluetoothSocket bluetoothSocket;
// This will block while listening until a BluetoothSocket is returned
// or an exception occurs
while (true) {
try {
bluetoothSocket = bluetoothServerSocket.accept();
Toast.makeText(getApplicationContext(), "Alert", <-------//the code is not run through here, there is no toast coming out
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
break;
}
// If a connection is accepted
if (bluetoothSocket != null) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "A connection has been accepted.",
Toast.LENGTH_SHORT).show();
}
});
// Manage the connection in a separate thread
try {
bluetoothServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
// Cancel the listening socket and terminate the thread
public void cancel() {
try {
bluetoothServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
there is no error shown but when i triggered the ListeningThread() function, this line of code is running Toast.makeText(getApplicationContext(), "Listening" it is shown that my server is listening to incoming connection
but when I'm using other client to connect to this server, then client are showing "paired" but on the server there is nothing shown, but the connection was actually successfull.
from the line
//This will block while listening until a BluetoothSocket is returned//or an exception occurs and //If a connection is acceptedis not running, because the toast did not coming out.
this function is called from MainActivity Threads and was putted on a button. I don't think pasting all the code here will be good, but here is the button codes. if there is anything you need to see, simply ask me.
serverBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ListeningThread t = new ListeningThread();
t.start();
}
});
I am currently trying to receive data on my android smartphone (version 4.4.4) send from my RFduino (some kind of arduino) via Bluetooth. Therefore i made a small android application.
Now everything works fine, until i try to connect my BluetoothSocket. First i got the an IOException: read failed -1 which i tried to solve like this:
IOException: read failed, socket might closed - Bluetooth on Android 4.3
Which worked. But now my application just freezes after i call connect(). I know that this is because the method blocks until it has found a connection, but why does this not connect?
My RFduino uses BluetoothBLE (low energy): Do i have to use the BluetoothGatt classes as counter-part?
Here is my code:
public BluetoothConnection(Activity parentActivity) {
this.mActivity = parentActivity;
findBluetooth();
openBluetooth();
}
private void findBluetooth() {
this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (this.mBluetoothAdapter == null) {
}
if (!this.mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
this.mActivity.startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = this.mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals("RFduino")) {
this.mBluetoothDevice = device;
break;
}
}
}
}
private void openBluetooth() {
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
BluetoothSocket tmp = this.mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
this.mBluetoothSocket = new NativeBluetoothSocket(tmp);
this.mBluetoothSocket.connect();
} catch (IOException e) {
// try the fallback
Log.w("BT", "Had to use fallback method!");
try {
this.mBluetoothSocket = new FallbackBluetoothSocket(this.mBluetoothSocket.getUnderlyingSocket());
Thread.sleep(500);
this.mBluetoothSocket.connect();
} catch (FallbackException e1) {
Log.w("BT", "Could not initialize FallbackBluetoothSocket classes.", e);
} catch (InterruptedException e1) {
Log.w("BT", e1.getMessage(), e1);
} catch (IOException e1) {
Log.w("BT", "Fallback failed. Cancelling.", e1);
}
}
try {
this.mInputStream = this.mBluetoothSocket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
While NativeBluetoothAdapter and FallbackBluetoothAdapter are depicted in the thread i posted above.
Thanks for any suggestions.
I am writing an IRC Client. The socket connection to the IRC Server is handled via a service. I have managed to stabilize all the UI elements of the Activities in question during the orientation change, but somehow the socket that is maintained by the service is being closed during the change.
Here is what I believe to be the relevant code. Please let me know if you need to see more.
//This is the Service in question
public class ConnectionService extends Service{
private BlockingQueue<String> MessageQueue;
public final IBinder myBind = new ConnectionBinder();
public class ConnectionBinder extends Binder {
ConnectionService getService() {
return ConnectionService.this;
}
}
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private IRCServer server;
private WifiManager.WifiLock wLock;
private Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String line;
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
queueMessage(line);
}
}
catch (Exception e) {}
}
});
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(MessageQueue == null)
MessageQueue = new LinkedBlockingQueue<String>();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return myBind;
}
#Override
public boolean stopService(Intent name) {
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.stopService(name);
}
#Override
public void onDestroy()
{//I put this here so I had a breakpoint in place to make sure this wasn't firing instead of stopService
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
public void SendMessage(String message)
{
try {
writer.write(message + "\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readLine()
{
try {
if(!isConnected())
return null;
else
return MessageQueue.take();
} catch (InterruptedException e) {
return "";
}
}
public boolean ConnectToServer(IRCServer newServer)
{
try {
//create a new message queue (connecting to a new server)
MessageQueue = new LinkedBlockingQueue<String>();
//lock the wifi
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "LockTag");
wLock.acquire();
server = newServer;
//connect to server
socket = new Socket();
socket.setKeepAlive(true);
socket.setSoTimeout(60000);
socket.connect(new InetSocketAddress(server.NAME, Integer.parseInt(server.PORT)), 10000);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//run basic login scripts.
if(server.PASS != "")
SendMessage("PASS " + server.PASS);
//write nickname
SendMessage("NICK " + server.NICK);
//write username login
SendMessage("USER " + server.NICK + " 0 * :Fluffy IRC");
String line;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
//change to alt Nick
if(!server.NICK.equals(server.ALT_NICK) && !server.ALT_NICK.equals(""))
{
server.NICK = server.ALT_NICK;
SendMessage("NICK " + server.NICK);
}
else
{
queueMessage("Nickname already in use");
socket.close();
return false;
}
}
else if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
{
queueMessage(line);
}
}
//start the reader thread AFTER the primary login!!!
CheckStartReader();
if(server.START_CHANNEL == null || server.START_CHANNEL == "")
{
server.WriteCommand("/join " + server.START_CHANNEL);
}
//we're done here, go home everyone
} catch (NumberFormatException e) {
return false;
} catch (IOException e) {
return false;
}
return true;
}
private void queueMessage(String line) {
try {
MessageQueue.put(line);
} catch (InterruptedException e) {
}
}
public boolean isConnected()
{
return socket.isConnected();
}
public void CheckStartReader()
{
if(this.isConnected() && !readThread.isAlive())
readThread.start();
}
}
//Here are the relevant portions of the hosting Activity that connects to the service
//NOTE: THE FOLLOWING CODE IS PART OF THE ACTIVITY, NOT THE SERVICE
private ConnectionService conn;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
conn = ((ConnectionService.ConnectionBinder)service).getService();
Toast.makeText(main_tab_page.this, "Connected", Toast.LENGTH_SHORT)
.show();
synchronized (_serviceConnWait) {
_serviceConnWait.notify();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
conn = null;
}
};
#Override
protected void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putParcelable("Server", server);
state.putString("Window", CurrentTabWindow.GetName());
unbindService(mConnection);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(this.isFinishing())
stopService(new Intent(this, ConnectionService.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_page);
localTabHost = (TabHost)findViewById(R.id.tabHostMain);
localTabHost.setup();
localTabHost.setOnTabChangedListener(new tabChange());
_serviceConnWait = new Object();
if(savedInstanceState == null)
{//initial startup, coming from Intent to start
//get server definition
server = (IRCServer)this.getIntent().getParcelableExtra(IRC_WINDOW);
server.addObserver(this);
AddTabView(server);
startService(new Intent(this, ConnectionService.class));
}
else
{
server = (IRCServer)savedInstanceState.getParcelable("Server");
String windowName = savedInstanceState.getString("Window");
//Add Needed Tabs
//Server
if(!(windowName.equals(server.GetName())))
AddTabView(server);
//channels
for(IRCChannel c : server.GetAllChannels())
if(!(windowName.equals(c.GetName())))
AddTabView(c);
//reset each view's text (handled by tabChange)
if(windowName.equals(server.GetName()))
SetCurrentTab(server.NAME);
else
SetCurrentTab(windowName);
ResetMainView(CurrentTabWindow.GetWindowTextSpan());
//Rebind to service
BindToService(new Intent(this, ConnectionService.class));
}
}
#Override
protected void onStart()
{
super.onStart();
final Intent ServiceIntent = new Intent(this, ConnectionService.class);
//check start connection service
final Thread serverConnect = new Thread(new Runnable() {
#Override
public void run() {
if(!BindToService(ServiceIntent))
return;
server.conn = conn;
conn.ConnectToServer(server);
server.StartReader();
if(server.START_CHANNEL != null && !server.START_CHANNEL.equals(""))
{
IRCChannel chan = server.FindChannel(server.START_CHANNEL);
if(chan != null)
{
AddTabView(chan);
}
else
{
server.JoinChannel(server.START_CHANNEL);
chan = server.FindChannel(server.START_CHANNEL);
AddTabView(chan);
}
}
}
});
serverConnect.start();
}
private boolean BindToService(Intent ServiceIntent)
{
int tryCount = 0;
bindService(ServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
while(conn == null && tryCount < 10)
{
tryCount++;
try {
synchronized (_serviceConnWait) {
_serviceConnWait.wait(1500);
}
}
catch (InterruptedException e) {
//do nothing
}
}
return conn != null;
}
Im not entirely certain what I am doing wrong there. Obviously there's something I'm missing, haven't found yet, or haven't even thought to check. What happens though is that after the orientation change my Send command gives me this message and nothing happens:
06-04 22:02:27.637: W/System.err(1024): java.net.SocketException: Socket closed
06-04 22:02:27.982: W/System.err(1024): at com.fluffyirc.ConnectionService.SendMessage(ConnectionService.java:90)
I have no idea when the socket is getting closed, or why.
Update
I have changed the code so that rather than binding to the service and using that to start it, instead I call startService and stopService at appropriate points as well as binding to it, on the thought that the service was being destroyed when the binding was lost. This is working exactly like it was before I changed it. The socket still closes on an orientation change, and I have no idea why.
Update :- Code and description
I added the code changes recently made for Start/Stop service and START_STICKY. I also recently read a very good article explaining how the orientation change process flow works and why its NOT a bad idea to add the android:configChanges="orientation|screenSize" line to your manifest. So this fixed the orientation issue, but its still doing the same thing if I put the activity into background mode, and then bring it back to the foreground. That still follows the same Save/Destroy/Create process that the orientation does without that manifest line...and it still closes my socket, and I still don't know why.
I do know that it doesn't close the socket until the re-create process...I know this because the message queue will display messages that were received while the app was in the background, but once I bring it back forward it closes the socket and nothing else can be sent or received.
'Socket closed' means that you closed the socket and then continued to use it. It isn't a 'disconnect'.
You need to put something into that catch block. Never just ignore an exception. You might get a surprise when you see what the exception actually was.
NB Socket.isConnected() doesn't tell you anything about the state of the connection: only whether you have ever connected the Socket. You have, so it returns true.
When I click the first time on login button, data send to server and server received data in return on first click data not show on android client screen. When I pressed login button again it again send data and then it show data on client screen... plz help me. Why data is received on secind click i want my data recived on my first click?
Here is the code :
Client tcpip code...
public class SockProg {
private Socket socket;
DataOutputStream dataOutputStream;
DataInputStream dataInputStream;
String data;
String serverip = "192.168.1.7";
int serverport = 4444;
public void connetToServer(){
try {
socket = new Socket(serverip, serverport);
Log.i("AsyncTank", "doInBackgoung: Created Socket");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (socket.isConnected()) {
try {
dataOutputStream = new DataOutputStream(
socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void writeToStream(String message) {
try {
if (socket.isConnected()){
dataOutputStream.writeUTF(message.toString());
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
public String readFromStream() {
String ret = null;
try {
if (socket.isConnected()) {
Log.i("AsynkTask", "readFromStream : Reading message");
ret=dataInputStream.readUTF();
Log.i("AsynkTask", "readFromStream : read "+ret);
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Reading failed"+e.getClass());
}
return ret;
}
public void CloseSockets(){
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
here is the code of sychronized thread
public class TCP implements Runnable {
String data;
SockProg sp;
Thread thh;
private static String rdata;
public TCP(SockProg spr, String val) {
sp = spr;
data = val;
thh = new Thread(this);
thh.start();
}
#Override
public void run() {
synchronized(sp) { // synchronized block
//rdata= sp.DataSendRecive(data);
sp.connetToServer();
sp.writeToStream(data);
rdata=sp.readFromStream();
sp.CloseSockets();
}
}
public static String getData(){
return rdata;
}
}
here is code of Login Activity...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
msg = (TextView) findViewById(R.id.msg_log);
login = (Button) findViewById(R.id.btn_login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// try{
txtph = (EditText) findViewById(R.id.txt_phnum);
txtpass = (EditText) findViewById(R.id.txt_pass);
ph = txtph.getText().toString();
pass = txtpass.getText().toString();
int ch = 0;
if (ph.equals("") || ph == null) {
msg.setText("Please Enter Mobile Number....\n");
ch++;
}
if (pass.equals("") || pass == null) {
if (ch == 0) {
msg.setText("Please Enter your Password....\n");
} else {
msg.append("Please Enter your Password....\n");
}
ch++;
}
if (ch == 0) {
ArrayList<String> ph_pass = new ArrayList<String>();
ph_pass.add(0, "LoginAccount");
ph_pass.add(1, ph);
ph_pass.add(2, pass);
SockProg sp=new SockProg();
TCP t=new TCP(sp, ph_pass.toString());
data=t.getData();
msg.setText(data);
}
}
});
}
This looks like a classic case of asynchronous coding delay. The TCP class is a runnable and therefor when it is called the first time (the first click on the login button) it starts running, but the Thread does not have enough time to finish
rdata=sp.readFromStream();
in the run() method, therefor data=t.getData(); does not return anything useful. The second click, provides the runnable with enough time populate the rdata with some data and therefor your program works.
When working with asynchrounous code, you need a better way to wait for code to complete what it is doing.
Why is rdata a static type? Make it non-static and then change the getData() method like this:
public synchronized String getData()