I have two classes:
MainActivity.class
ScreenCapture.class
and want getOutputStream(); from a Socket that is located on MainActivity.class.
Then i do:
MainActivity.INSTANCE.clientSocket.getOutputStream();
but is failing in this line ^, i not left logcat here because my logcat not is catching all events correctly, but from this description hope that someone can help.
MainActivity
public class MainActivity extends AppCompatActivity {
public static final MainActivity INSTANCE = new MainActivity();
public Socket clientSocket;
private final int SERVERPORT = 101;
private final String SERVER_IP = "192.168.15.13";
/////////////////////////////////////////////// CLIENTSOCKET //////////////////////////////////////////////////////
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
clientSocket = new Socket(serverAddr, SERVERPORT);
new Thread(new CommsThread()).start();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
class CommsThread implements Runnable {
#Override
public void run() {
try {
System.out.println("Waiting for server request");
while(clientSocket.isConnected()){
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())),true);
if (reader.ready()) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if(line != null && !line.trim().isEmpty()) {
if(line.equalsIgnoreCase("screen")){
// Do something
out.flush();
}
if(line.equalsIgnoreCase("exit")) break;
}
}
}
Thread.sleep(100);
}
System.out.println("Shutting down Socket!!");
clientSocket.close();
} catch (Exception e1) {
System.out.println(e1.toString());
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new ClientThread()).start();
}
ScreenCapture
public class ScreenCaptureClass {
#UiThread
public boolean takeScreenshot(#NonNull Context context) {
//...
imageReader.setOnImageAvailableListener(new OnImageAvailableListener() {
#Override
public void onImageAvailable(final ImageReader reader) {
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(final Void... params) {
// ...
OutputStream outs = MainActivity.INSTANCE.clientSocket.getOutputStream(); // <= Error is here
}
}
}
}
}
}
Try to pass the socket's reference to your ScreenCaptureClass, you can try the following things:
You can pass your socket through the ScreenCaptureClass constructor (probably the best way).
Inside your ScreenCaptureClass you can add a static variable like private static OutputStream outputStream and a setter called from your MainActivity :
public static void setOutputStream(OutputStream os) {
outputStream = os;
}
Related
I am looking for a way to send received data (receive while flag is set) from a socket service to an activity that is bound to the service. What is the best way to do this ? Handlers , AsyncTask or something else ?
this is the SocketClass I am using to start a connection and handle the incoming messages :
class connectSocket implements Runnable {
#Override
public void run() {
running= true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(running){
msg = (Message) mBufferIn.readObject();
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
Update :
public class SocketService extends Service {
private static final String TAG = "com.oos.kiesa.chat";
public static final String SERVERIP = "192.168.X.X";
public static final int SERVERPORT = 4444;
private ObjectOutputStream mBufferOut;
private ObjectInputStream mBufferIn;
Socket socket;
InetAddress serverAddr;
boolean mRun;
Object msg;
public Integer command;
#Override
public IBinder onBind(Intent intent) {
return myBinder;
}
private final IBinder myBinder = new LocalBinder();
public class LocalBinder extends Binder {
public SocketService getService() {
return SocketService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
public void IsBoundable(){
Toast.makeText(this,"is boundable", Toast.LENGTH_LONG).show();
}
public void sendMessage(String message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(Message message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(User user) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(user);
mBufferOut.flush();
}
}
public void sendMessage(int command) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeInt(command);
mBufferOut.flush();
}
}
#Override
public int onStartCommand(Intent intent,int flags, int startId){
super.onStartCommand(intent, flags, startId);
System.out.println("I am in on start");
Runnable connect = new connectSocket();
new Thread(connect).start();
return START_STICKY;
}
public void stopClient() throws IOException{
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mBufferIn = null;
mBufferOut = null;
socket.close();
}
class connectSocket implements Runnable {
#Override
public void run() {
mRun = true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(mRun){
switch(command.intValue()){
case Constants.ADD_MESSAGE:
msg = (Message) mBufferIn.readObject(); // send message to Activity
break;
}
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
socket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
}
Some guidance / examples would be greatly appreciated
I am sending you mine, hope it will help :
class SocketRequestHandler extends Thread {
static String EOF = "<EOF>";
TCPResponseModel tcpResponseDS;
Activity activity;
boolean doSkip = false;
String responseStringComplete = "";
Socket clientSocekt;
OutputStream clientSocketOutputStream;
PrintWriter clinetSocketPrintWriter;
DataInputStream clientSocketInputStream;
private SocketRequestHandler(TCPResponseModel tcpResponseDS, Activity activity, SaloonListener listener) {
this.tcpResponseDS = tcpResponseDS;
this.activity = activity;
this.listener = listener;
moreStores = tcpResponseDS.StoresFound;
}
public static SocketRequestHandler pingAll(Activity activity, TCPResponseModel tcpResponseDS, SaloonListener listener) {
SocketRequestHandler requestHandler = new SocketRequestHandler(tcpResponseDS, activity, listener);
requestHandler.start();
return requestHandler;
}
private void closeStreams() {
try {
clientSocekt.close();
clientSocketInputStream.close();
clinetSocketPrintWriter.close();
clientSocketOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
String pingingHost = "URL_TO_PING";
clientSocekt = new Socket(pingingHost, 12000);
clientSocketOutputStream = clientSocekt.getOutputStream();
clinetSocketPrintWriter = new PrintWriter(clientSocketOutputStream);
String firstPing = "{\"RequestId\":" + tcpResponseDS.RequestId + "}<EOF>";
clinetSocketPrintWriter.println(firstPing);
clinetSocketPrintWriter.flush();
byte[] bytes;
String pingStr = "";
clientSocketInputStream = new DataInputStream(clientSocekt.getInputStream());
while (true) {
bytes = new byte[1024];
clientSocketInputStream.read(bytes);
bytes = trim(bytes);
if (bytes.length > 0 && !doSkip) {
String newString = new String(bytes, "UTF-8");
String decoded = pingStr + newString;
pingStr = checkForMessage(decoded);
responseStringComplete += newString;
}
if (doSkip) {
break;
}
}
closeStreams();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.print(responseStringComplete);
}
}
}
To broadcast chat data just do :
msg = (Message) mBufferIn.readObject(); // Do code after this line
Intent localIntent = new Intent("CHAT_MESSAGE");
localIntent.putExtra("message", msg);
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
Now in the activity where you are showing the chat list you can do
class ReceiveMessages extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals("CHAT_MESSAGE")) {
runOnUiThread(new Runnable() {
#Override
public void run() {
String chatMessage = getIntent().getStringExtra("message");
//get data from intent and update your chat list.
}
});
}
}
}
ReceiveMessages myReceiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your code
myReceiver = new ReceiveMessages();
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver,
new IntentFilter("CHAT_MESSAGE"));
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
}
public class AsyncHttpClient {
public AsyncHttpClient() {
}
public static class SocketIORequest {
private String mUri;
private String mEndpoint;
private List<BasicNameValuePair> mHeaders;
public SocketIORequest(String uri) {
this(uri, null);
}
public SocketIORequest(String uri, String endpoint) {
this(uri, endpoint, null);
}
public SocketIORequest(String uri, String endpoint, List<BasicNameValuePair> headers) {
mUri = Uri.parse(uri).buildUpon().encodedPath("/socket.io/1/").build().toString();
mEndpoint = endpoint;
mHeaders = headers;
}
public String getUri() {
return mUri;
}
public String getEndpoint() {
return mEndpoint;
}
public List<BasicNameValuePair> getHeaders() {
return mHeaders;
}
}
public static interface StringCallback {
public void onCompleted(final Exception e, String result);
}
public static interface WebSocketConnectCallback {
public void onCompleted(Exception ex, WebSocketClient webSocket);
}
public void executeString(final SocketIORequest socketIORequest, final StringCallback stringCallback) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
AndroidHttpClient httpClient = AndroidHttpClient.newInstance("android-websockets-2.0");
HttpPost post = new HttpPost(socketIORequest.getUri());
addHeadersToRequest(post, socketIORequest.getHeaders());
try {
HttpResponse res = httpClient.execute(post);
String responseString = readToEnd(res.getEntity().getContent());
if (stringCallback != null) {
stringCallback.onCompleted(null, responseString);
}
} catch (IOException e) {
if (stringCallback != null) {
stringCallback.onCompleted(e, null);
}
} finally {
httpClient.close();
httpClient = null;
}
return null;
}
private void addHeadersToRequest(HttpRequest request, List<BasicNameValuePair> headers) {
if (headers != null) {
Iterator<BasicNameValuePair> it = headers.iterator();
while (it.hasNext()) {
BasicNameValuePair header = it.next();
request.addHeader(header.getName(), header.getValue());
}
}
}
}.execute();
}
private byte[] readToEndAsArray(InputStream input) throws IOException {
DataInputStream dis = new DataInputStream(input);
byte[] stuff = new byte[1024];
ByteArrayOutputStream buff = new ByteArrayOutputStream();
int read = 0;
while ((read = dis.read(stuff)) != -1) {
buff.write(stuff, 0, read);
}
return buff.toByteArray();
}
private String readToEnd(InputStream input) throws IOException {
return new String(readToEndAsArray(input));
}
I've recently made a simple multicast client - server chat for java, now i am attempting to port the client on android.
The issue i'm facing is about dealing with the socket: the socket is created in a thread (as it'd crash the app otherwise), then i use the socket to istantiate an InputStreamReader and an OutputStreamWriter, however when trying to access any object created this way through a button listener, i'll get a null exception.
Also, if i were to put the two readers outside the thread, they would generate a null exception as well, even if i make sure the socket has been created already inside the thread.
I'd be glad if anybody could help me find out where is the issue, i apology for the messy code
public class ClientActivity extends AppCompatActivity {
public static int PORT = 1050;
public static String ADDRESS = "";
public static String USERNAME = "";
SusListenerThread inT;
public int ID;
public int roomID;
Socket socket = null;
BufferedReader in = null, stdIn = null;
PrintWriter out = null;
InputStreamReader isr;
OutputStreamWriter osw;
String userInput="";
public int mode=1;
public Button Bsend;
public Button Bbroadcast;
public Button Broom;
public EditText editMessage;
public EditText editReplies;
public EditText editRoom;
public TextView txtID;
public TextView txtUsername;
public TextView txtRoom;
public connectSocket coSocket;
public ClientActivity() {
}
public void setStuff(String str, int IDh){
this.ID=IDh;
this.USERNAME=str;
txtID.setText("ID: "+IDh);
txtUsername.setText("Username: "+str);
}
private class SusListenerThread extends Thread{
BufferedReader in = null;
public int ID;
public String username;
public boolean isSet=false;
//public View viiv;
public EditText editReplies;
public TextView txtRoom;
public SusListenerThread(InputStreamReader isr){
//this.viiv=viiv;
//editReplies = (EditText)viiv.findViewById(R.id.editReplies);
//txtRoom = (TextView)viiv.findViewById(R.id.textRoom);
in = new BufferedReader(isr);
//ClientGUI.jTextArea1.append(joj+"\n");
start();
}
#Override
public void run(){
String input="";
getStuff();
while(true)
{
try {
input=in.readLine();
} catch (IOException ex) {
//Logger.getLogger(ListenerThread.class.getName()).log(Level.SEVERE, null, ex);
}
if(input.charAt(0)=='0')
//ClientGUI.jTextArea1.append(input.substring(1)+"\n");
editReplies.append(input.substring(1)+"\n");
else if(input.charAt(0)=='1'){
//ClientGUI.jLabel2.setText("Stanza:"+input.substring(1));
txtRoom.setText("Room: "+input.substring(1));
}
}
}
public void getStuff(){
try {
ID=Integer.parseInt(in.readLine());
username+=in.readLine();
} catch (IOException ex) {
}
isSet=true;
}
}
private class connectSocket extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void result) {
}
#Override
protected Void doInBackground(Void... params) {
try {
socket= new Socket(ADDRESS,PORT);
} catch (IOException e) {
try {
socket = new Socket("127.0.0.1", 1050);
}catch(Exception ex){
e.printStackTrace();
};
}
/*
try{
isr = new InputStreamReader ( socket.getInputStream());
//in = new BufferedReader(isr);
inT=new SusListenerThread(isr);
osw = new OutputStreamWriter ( socket.getOutputStream());
BufferedWriter bw = new BufferedWriter( osw );
out = new PrintWriter (bw, true);
} catch (IOException ex) {}
*/
return null;
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
private class lilThread extends Thread {
public lilThread(){
start();
}
#Override
public void run(){
try {
socket = new Socket(ADDRESS, PORT);
}catch(Exception e ){
try {
socket = new Socket("79.42.49.56", 1050);
} catch (IOException ex) {ex.printStackTrace();}
}
try {
isr = new InputStreamReader ( socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
inT=new SusListenerThread(isr);
try {
osw = new OutputStreamWriter ( socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
BufferedWriter bw = new BufferedWriter( osw );
out = new PrintWriter (bw, true);
while(!inT.isSet){
try {
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setStuff(inT.username.substring(4)/*Mi ritornava nullUtente invece di Utente*/, inT.ID);
try {
wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
join();
} catch (InterruptedException e) {
e.printStackTrace();
}
interrupt();
}
}
public void InitializeStuff(){
lilThread lil = new lilThread();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_activity_gui);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
Bsend = (Button)findViewById(R.id.buttonSenderino);
Bbroadcast = (Button)findViewById(R.id.buttonBroadcast);
Broom = (Button)findViewById(R.id.buttonRoom);
editMessage = (EditText)findViewById(R.id.editMessage);
editReplies = (EditText)findViewById(R.id.editReplies);
editRoom = (EditText)findViewById(R.id.editRoom);
txtID = (TextView)findViewById(R.id.textID);
txtUsername = (TextView)findViewById(R.id.textUsername);
txtRoom = (TextView)findViewById(R.id.textRoom);
this.PORT = getIntent().getExtras().getInt("PORT");
this.ADDRESS = getIntent().getExtras().getString("ADDRESS");
this.USERNAME = getIntent().getExtras().getString("USERNAME");
InitializeStuff();
Bsend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//userInput= (EditText)v.findViewById(R.id.editMessage).getco;
userInput = editMessage.getText().toString();
if (!"".equals(userInput)) {
out.println(3 + userInput);
editMessage.setText("");
}
}
});
Bbroadcast.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mode=0;
txtRoom.setText("Room: Broadcast");
roomID=-1;
out.println(mode);
editMessage.setText("");
}
});
Broom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mode=2;
try{
roomID=Integer.parseInt(editRoom.getText().toString());
txtRoom.setText("Stanza: "+roomID);
out.println(mode+""+roomID);
editRoom.setText("");
}catch(Exception e){
txtRoom.setText(" Err ");
}
}
});
}
}
According to an google example, i write an android client for a connection protocol based on TCP Socket server can send and receive information and it works good. But now I want it to become a background service for these transactions, after I left the application it also can notify me the message in time, I think a couple of days, but without success, someone can give me some help? Very grateful!
MainActivity
public class MainActivity extends Activity implements
Handler.Callback, ChatFragment.MessageTarget {
public static final String TAG = "rolingbaby";
public static final int MESSAGE_READ = 0x400 + 1;
public static final int MESSAGE_SEND = 0x400 + 2;
public static final String SERVER_URL = "192.168.191.2";
public static final int SERVER_PORT = 7838;
private Handler handler = new Handler(this);
private ChatFragment chatFragment;
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
InetAddress address = InetAddress.getByName(SERVER_URL);
Log.d(TAG, "Connected success!");
new MyTask1(((ChatFragment.MessageTarget) this).getHandler(),
address).execute();
} catch (UnknownHostException e) {
e.printStackTrace();
}
chatFragment = new ChatFragment();
getFragmentManager().beginTransaction()
.add(R.id.container, chatFragment, "trans")
.commit();
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, readMessage);
(chatFragment).pushMessage("Rec: " + readMessage);
break;
case MESSAGE_SEND:
Object obj = msg.obj;
(chatFragment).setChatManager((ChatManager) obj);
}
return true;
}
#Override
protected void onPause() {
super.onPause();
finish();
}
}
Pivotal code in ChatFragment
public interface MessageTarget {
public Handler getHandler();
}
public void setChatManager(ChatManager obj) {
chatManager = obj;
}
public void pushMessage(String readMessage) {
adapter.add(readMessage);
adapter.notifyDataSetChanged();
}
MyTask
public class MyTask extends AsyncTask<Void, Void, Void>{
private static final String TAG = "ClientSocketHandler";
private Handler handler;
private ChatManager chat;
private InetAddress mAddress;
private static final int timeOut = 5000;
public MyTask(Handler handler, InetAddress serverAddress) {
this.handler = handler;
this.mAddress = serverAddress;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = new Socket();
try {
socket.bind(null);
socket.connect(new InetSocketAddress(mAddress.getHostAddress(),
MainActivity.SERVER_PORT), timeOut);
Log.d(TAG, "Launching the I/O handler");
chat = new ChatManager(socket, handler);
new Thread(chat).start();
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
public ChatManager getChat() {
return chat;
}
}
ChatManager
public class ChatManager implements Runnable {
private Socket socket = null;
private Handler handler;
public ChatManager(Socket socket, Handler handler) {
this.socket = socket;
this.handler = handler;
}
private InputStream iStream;
private OutputStream oStream;
private static final String TAG = "ChatHandler";
public static String readMessage;
#Override
public void run() {
try {
iStream = socket.getInputStream();
oStream = socket.getOutputStream();
byte[] buffer = new byte[1024];
int bytes;
handler.obtainMessage(MainActivity.MESSAGE_SEND, this)
.sendToTarget();
while (true) {
try {
// Read from the InputStream
bytes = iStream.read(buffer);
if (bytes == -1) {
break;
}else{
readMessage = new String(buffer, "UTF-8");
}
// Send the obtained bytes to the UI Activity
Log.d(TAG, "Rec:" + String.valueOf(buffer));
handler.obtainMessage(MainActivity.MESSAGE_READ,
bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] buffer) {
try {
oStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
}
Code first:
public class MyActivity extends Activity {
Button send;
TextView textv;
String answer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
send = (Button)findViewById(R.id.sendButton);
textv = (TextView)findViewById(R.id.textViewv);
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
MyClientTask myClientTask = new MyClientTask("localhost", 1234, "QUESTION");
myClientTask.execute();
}
});
}
void processAnswer() {
Log.i("DEBUG", "in processAnswer - before setting text");
Log.i("DEBUG", "ANSWER");
textv.setText("ANSWER\n"); // <-------- H E R E -----------
Log.i("DEBUG", "in processAnswer - after setting text");
}
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String message;
String response;
MyClientTask(String addr, int port, String msg){
dstAddress = addr;
dstPort = port;
message = msg;
response = "";
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
InetAddress serverAddr = InetAddress.getByName(dstAddress);
socket = new Socket(serverAddr, dstPort);
OutputStream out = socket.getOutputStream();
out.write(message.getBytes());
out.flush();
String msgrc = "";
int charsRead = 0;
char[] inputBuf = new char[4096];
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader in = new BufferedReader(isr);
while ((charsRead = in.read(inputBuf)) != -1) {
msgrc += new String(inputBuf).substring(0, charsRead);
}
// outer class variable
MyActivity.this.answer = msgrc;
out.close();
is.close();
socket.close();
Log.i("DEBUG", "before processing answer");
MyActivity.this.processAnswer();
Log.i("DEBUG", "after processing answer");
} catch (Exception e) {
}
return null;
}
}
}
The code above simply sends some message to a server and receives an answer. This answer should then be displayed in the TextView (see marked line). However, the app hangs at that line, i.e, LogCat displays
[...]
before processing answer
in processAnswer - before setting text
ANSWER
Then no more lines are written to LogCat. Has anybody an explanation for that? If the marked line is commented out, LogCat looks like
[...]
before processing answer
in processAnswer - before setting text
ANSWER
in processAnswer - after setting text
after processing answer
If you move your call to MyActivity.this.processAnswer() to onPostExecute() instead, perhaps that might work - IIRC, items on the UI thread should only be updated from the UI thread.
First inialize your text view by following , then add onPostExecute method bellow the doInBackground
method . And set your text there . Bellow is code which i change.
public class MyActivity extends Activity {
Button send;
TextView textv;
String answer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
send = (Button)findViewById(R.id.sendButton);
textv = (TextView)findViewById(R.id.textview);
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
MyClientTask myClientTask = new MyClientTask("localhost", 1234, "QUESTION");
myClientTask.execute();
}
});
}
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String message;
String response;
MyClientTask(String addr, int port, String msg){
dstAddress = addr;
dstPort = port;
message = msg;
response = "";
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
InetAddress serverAddr = InetAddress.getByName(dstAddress);
socket = new Socket(serverAddr, dstPort);
OutputStream out = socket.getOutputStream();
out.write(message.getBytes());
out.flush();
String msgrc = "";
int charsRead = 0;
char[] inputBuf = new char[4096];
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader in = new BufferedReader(isr);
while ((charsRead = in.read(inputBuf)) != -1) {
msgrc += new String(inputBuf).substring(0, charsRead);
}
// outer class variable
MyActivity.this.answer = msgrc;
out.close();
is.close();
socket.close();
Log.i("DEBUG", "before processing answer");
MyActivity.this.processAnswer();
Log.i("DEBUG", "after processing answer");
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
textv.setText(msgrc);
}
}
}
I am just getting the first 30 lines, how can I view the new lines being generated in my application, here is my code:
package com.example.showinlog;
public class ShowingLog extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Process process = Runtime.getRuntime().exec("logcat");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
log.append("\n");
}
TextView tv = (TextView)findViewById(R.id.textView1);
tv.setText(log.toString());
} catch (IOException e) {
}
}
}
I'm actually not sure how you get anything. The reading shouldn't ever "end", and since you don't do your reading in a different thread, you should never get to the part where you initialize the TextView.
Even if you did get to a point where you can continually log text, it wouldn't work with this code because you'd never be "done" building your StringBuilder.
Try this. You'll need to pass in a LogcatOut as a callback for the log data:
public class LolCat
{
private Process proc;
private LogcatOut logcatOut;
public LolCat(LogcatOut logcatOut)
{
this.logcatOut = logcatOut;
}
private InputStream inStd;
private InputStream inErr;
private LogcatProcessStreamReader streamReader;
private LogcatProcessStreamReader errStreamReader;
public void start()
{
try
{
proc = Runtime.getRuntime().exec("logcat");
OutputStream os = proc.getOutputStream();
this.inStd = proc.getInputStream();
this.inErr = proc.getErrorStream();
startReaders();
os.flush();
}
catch (IOException e)
{
// App.logExecption("Can't logcat", e);
}
catch (Exception e1)
{
// App.logExecption("Can't logcata", e1);
}
}
private void startReaders() throws FileNotFoundException
{
this.streamReader = new LogcatProcessStreamReader(this.inStd, logcatOut);
this.errStreamReader = new LogcatProcessStreamReader(this.inErr, null);
streamReader.start();
errStreamReader.start();
}
public void kill()
{
proc.destroy();
if (this.streamReader != null)
this.streamReader.finish();
if (this.errStreamReader != null)
this.errStreamReader.finish();
}
public abstract class LogcatOut
{
public abstract void writeLogData(byte[] data, int read) throws IOException;
protected void cleanUp()
{
}
}
class LogcatProcessStreamReader extends Thread
{
private InputStream in;
private boolean done = false;
private LogcatOut logcatOut;
public LogcatProcessStreamReader(InputStream in, LogcatOut logcatOut)
{
this.in = in;
this.logcatOut = logcatOut;
}
#Override
public void run()
{
byte[] b = new byte[8 * 1024];
int read;
try
{
while (!done && ((read = in.read(b)) != -1))
{
if(logcatOut != null)
logcatOut.writeLogData(b, read);
}
if(logcatOut != null)
logcatOut.cleanUp();
}
catch (IOException e)
{
// App.logExecption("Can't stream", e);
}
}
public synchronized void finish()
{
done = true;
}
}
}
In your onCreate:
final Handler handler = new Handler();
new LolCat(new LolCat.LogcatOut()
{
#Override
public void writeLogData(final byte[] data, final int read) throws IOException
{
handler.post(new Runnable()
{
public void run()
{
TextView tv = (TextView) asdf;
tv.setText(tv.getText() + "\n" + new String(data, 0, read));
}
});
}
});
A few caveats:
1) I adapted this from other code I have. I HAVE NOT tested it. You may hit a null pointer exception or the like, but the basic code should work.
2) You do need the log permission (forget what that is)
3) I don't remember if the log data comes from std out or err out. I think its std, but if you're getting nothing, swap.
4) I would not recommend concatting text like I did in here in a text view. You'll need to implement a buffer that can be limited, and large string concats are obviously bad in Java. I'll leave that solution to the reader...
I found the AsyncTasks very useful when trying to implement this.
public class LogCatTask extends AsyncTask<Void, String, Void> {
public AtomicBoolean run = new AtomicBoolean(true);
#Override
protected Void doInBackground(Void... params) {
try {
Runtime.getRuntime().exec("logcat -c");
Process process = Runtime.getRuntime().exec("logcat");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder log = new StringBuilder();
String line = "";
while (run.get()) {
line = bufferedReader.readLine();
if (line != null) {
log.append(line);
publishProgress(log.toString());
}
line = null;
Thread.sleep(10);
}
}
catch(Exception ex){
}
return null;
}
}
And to implement the task you do something like
public void setupTextView(){
textView.setMovementMethod(new ScrollingMovementMethod());
logCatTask = new LogCatTask(){
#Override
protected void onProgressUpdate(String... values) {
textView.setText(values[0]);
super.onProgressUpdate(values);
}
};
logCatTask.execute();
}