问题
I searched for some websites and learned that the way to communicate between android device(phone) and PC via USB is to have an app implementing serversocket on the phone and another app implementing client socket on PC. I kinda fixed the phone side's app(no exception now), but I got an exception "Ljava.lang.StackTraceElement" trying to initiate a socket("localhost", 38300). Does anybody know what's going on with this and how I can fix it? I attached both side's of the code below.
My step to get it to run is as follows
: environment:
Samsung Android phone, Linux PC, Android Studio developer run on Linux
: connection step
- open android studio
- install one app on phone
- install another app on pc android emulator
- launch phone side app and click on button to attempt to wait for connection at this step, adb devices will have two devices
- adb -s emulator-5554 -s 1234567890(my phone) forward tcp:38300 tcp:38300
- launch pc side android emulator app and click on the button to initiate client socket
NOTE: as you all can see that I can use android studio "Android Monitor" window to see both phone's and PC's app shell's log.
phone side
package com.example.seanhsu.androiddevice_serversocket;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Scanner;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class AndroidDevice_ServerSocket extends AppCompatActivity implements OnClickListener{
public static final String TAG = "Connection";
public static final int TIMEOUT = 10;
Intent i = null;
TextView tv = null;
private String connectionStatus = null;
private String socketData = null;
private Handler mHandler = null;
ServerSocket server = null;
String msg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_device__server_socket);
// Set up click listeners for the buttons
View connectButton = findViewById(R.id.connect_button);
connectButton.setOnClickListener(this);
View onBtn = findViewById(R.id.hdmi_on);
onBtn.setOnClickListener(this);
View offBtn = findViewById(R.id.hdmi_off);
offBtn.setOnClickListener(this);
// i = new Intent(this, Connected.class);
mHandler = new Handler();
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.connect_button:
tv = (TextView) findViewById(R.id.connection_text);
// initialize server socket in a new separate thread
new Thread(initializeConnection).start();
msg = "Attempting to connect...";
Log.e(TAG, "1 "+msg);
Toast.makeText(this, msg, Toast.LENGTH_SHORT/*msg.length()*/).show();
break;
case R.id.hdmi_on:
Log.e(TAG, "disconnect" + Globals.socketOut);
if (Globals.socketOut != null) {
Globals.socketOut.println("hdmiOn");
Globals.socketOut.flush();
msg = "disconnect hdmi on";
Log.e(TAG, "2 "+msg);
Toast.makeText(this, msg, Toast.LENGTH_SHORT/*msg.length()*/).show();
}
else
{
msg = "disconnect hdmi on is null";
Log.e(TAG, "3 "+msg);
Toast.makeText(this, msg, Toast.LENGTH_SHORT/*msg.length()*/).show();
}
break;
case R.id.hdmi_off:
Log.e(TAG, "disconnect" + Globals.socketOut);
if (Globals.socketOut != null) {
Globals.socketOut.println("hdmiOff!!");
Globals.socketOut.flush();
msg = "disconnect hdmi off";
Log.e(TAG, "4 "+msg);
Toast.makeText(this, msg, Toast.LENGTH_SHORT/*msg.length()*/).show();
}
else
{
msg = "disconnect hdmi off is null";
Log.e(TAG, "5 "+msg);
Toast.makeText(this, msg, Toast.LENGTH_SHORT/*msg.length()*/).show();
}
break;
}
}
private Runnable initializeConnection = new Thread() {
public void run() {
Socket client = null;
// initialize server socket
try {
server = new ServerSocket(38300);
server.setSoTimeout(TIMEOUT * 5000);
// attempt to accept a connection
client = server.accept();
Globals.socketIn = new Scanner(client.getInputStream());
Globals.socketOut = new PrintWriter(client.getOutputStream(),
true);
// Globals.socketIn.
} catch (SocketTimeoutException e) {
// print out TIMEOUT
Log.e(TAG, "aaa=== " + e);
msg = "Connection has timed out! Please try again";
Log.e(TAG, "6 "+msg);
//Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();//method error, this causes program terminated
mHandler.post(showConnectionStatus);
} catch (IOException e) {
Log.e(TAG, "bbb=== " + e);
msg = "IO Exception";
Log.e(TAG, "7 "+msg);
//Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();//method error, this causes program terminated
} finally {
// close the server socket
try {
if (server != null)
server.close();
} catch (IOException ec) {
Log.e(TAG, "ccc=== " + ec);
Log.e(TAG, "Cannot close server socket" + ec);
msg = "Cannot close server socket";
Log.e(TAG, "8 "+msg);
//Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();//method error, this causes program terminated
}
}
if (client != null) {
Globals.connected = true;
// print out success
connectionStatus = "Connection was succesful!";
Log.e(TAG, "9 "+connectionStatus);
mHandler.post(showConnectionStatus);
while (Globals.socketIn.hasNext()) {
socketData = Globals.socketIn.next();
mHandler.post(socketStatus);
}
// startActivity(i);
}
}
};
/**
* Pops up a "toast" to indicate the connection status
*/
private Runnable showConnectionStatus = new Runnable() {
public void run() {
Log.e(TAG, "10 "+connectionStatus);
Toast.makeText(getBaseContext(), connectionStatus,
Toast.LENGTH_SHORT).show();
}
};
private Runnable socketStatus = new Runnable() {
public void run() {
TextView tv = (TextView) findViewById(R.id.connection_text);
tv.setText(socketData);
}
};
public static class Globals {
public static boolean connected;
public static Scanner socketIn;
public static PrintWriter socketOut;
}
}
PC side
package com.example.seanhsu.pchost_clientsocket_withactivity;
import android.support.v7.app.AppCompatActivity;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Scanner;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class PCHost_ClientSocket_with_Activity extends AppCompatActivity implements OnClickListener{
Socket socket;
PrintWriter out;
Scanner sc;
String msg;
private String TAG = "PCHost_ClientSocket_withActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pchost__client_socket_with_);
View connectButton = findViewById(R.id.connect_button);
connectButton.setOnClickListener(this);
//when the emulator start running, it's already in the emulator shell, so it cann't execute adb command
//execAdb();
}
public void onClick(View v) {
//cannot run on main thread
//need to run on another thread, otherwise it will get android.os.NetworkOnMainThreadException exception
new Thread(initializeConnection).start();
//initializeConnection();
/*while(sc.hasNext()) {
System.out.println(System.currentTimeMillis() + " / " + sc.nextLine());
Log.e(TAG, "12 "+System.currentTimeMillis() + " / " + sc.nextLine());
}*/
}
//cannot run on main thread
//need to run on another thread, otherwise it will get android.os.NetworkOnMainThreadException exception
private Runnable initializeConnection = new Thread() {
public void run() {
msg = "initializeConnection";
Log.e(TAG, msg);
//Create socket connection
try{
Log.e(TAG, "============0============");
socket = new Socket("localhost", 38300);
Log.e(TAG, "============1============");
out = new PrintWriter(socket.getOutputStream(), true);
Log.e(TAG, "============2============");
//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
sc=new Scanner(socket.getInputStream());
Log.e(TAG, "============3============");
// add a shutdown hook to close the socket if system crashes or exists unexpectedly
Thread closeSocketOnShutdown = new Thread() {
public void run() {
try {
Log.e(TAG, "============4============");
socket.close();
msg = "closeSocketOnShutdown socket close";
Log.e(TAG, msg);
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, "============5============");
e.printStackTrace();
msg = "closeSocketOnShutdown IOException";
Log.e(TAG, msg);
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
}
};
Log.e(TAG, "============6============");
Runtime.getRuntime().addShutdownHook(closeSocketOnShutdown);
Log.e(TAG, "============7============");
} catch (UnknownHostException e) {
//Print.fatalError(“Socket connection problem (Unknown host)”+e.getStackTrace());
msg = "Socket connection problem (Unknown host)"+e.getStackTrace();
Log.e(TAG, msg);
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
//Print.fatalError(“Could not initialize I/O on socket “+e.getStackTrace());
msg = "Could not initialize I/O on socket "+e.getStackTrace();
Log.e(TAG, msg);
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
}
};
}
I keep getting exception:
Could not initialize I/O on socket [Ljava.lang.StackTraceElement;@14710f5
Originally I also has IO exception on phone side app, but I add <uses-permission android:name="android.permission.INTERNET"/> in the manifest, it's OK now. Therefore, I also add <uses-permission android:name="android.permission.INTERNET"/> in PC side app's manifest, but still can't fix this problem.
来源:https://stackoverflow.com/questions/34036056/communication-between-android-devicephone-and-pc-via-usb-coding