Could you help me figure out how to implement Threads to this, so it won't freeze while it waits for the answer from the server?
I've tried for 5 hours or so, i simple can't find a way to use it in a thread, and then return it to set the text with tv.setText();
package zee.rhs.dk;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class AndroidClientActivity extends Activity {
private String ip = "90.184.254.246";
private int port = 8081;
private String line;
private TextView tv;
private Button btn;
private Socket socket;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ip, port);
out = new PrintWriter(socket.getOutputStream(), true);
out.println("update");
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
while ((line = in.readLine()) == null) {
}
tv.setText(line);
} catch (UnknownHostException e) {
Toast.makeText(AndroidClientActivity.this,
"Can't reach ip: " + ip, Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(AndroidClientActivity.this,
"Accept failed at port: " + port, Toast.LENGTH_LONG)
.show();
e.printStackTrace();
} finally {
out.close();
}
}
});
}
}
AsyncTask is what you're looking for. From the help page:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Remember that doInBackground runs in a separate thread, and onPostExecute runs in the UI thread after doInBackground completes.
Put your code, that is responsible for request to server into a separate thread:
Thread thread = new Thread() {
#Override
public void run() {
try {
// put your socket operations here
} catch (InterruptedException e) {
// handle exception if you need
}
}
};
thread.start();
Related
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
#TargetApi(18)
public class MainActivity extends AppCompatActivity{
`int b = 0;
BluetoothAdapter BA = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device;
BluetoothSocket BS;
BluetoothServerSocket server;
UUID uuid = UUID.fromString("f63b93f5-56e0-47bb-8972-996e34cfb9a8");`
`#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);`
`Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(i);`
`Accept accept = new Accept();
accept.start();`
Set<BluetoothDevice> devices = BA.getBondedDevices();
for(BluetoothDevice bt : devices) {
try {
if (bt.getName().equals("Overlord")) {
device = BA.getRemoteDevice(bt.getAddress());
BS = device.createRfcommSocketToServiceRecord(uuid);
} else if (bt.getName().equals("Huawei Y5")) {
device = BA.getRemoteDevice(bt.getAddress());
BS = device.createRfcommSocketToServiceRecord(uuid);
}
}catch(IOException IOE){}
}
}
public interface MessageContents{
int MSG_MESSAGE = 0;
}
Handler handler = new Handler(){
public void handleMessage(Message msg) {
TextView tx = (TextView)findViewById(R.id.textView2);
switch(msg.what){
case MessageContents.MSG_MESSAGE:
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);
tx.setText(readMessage);
break;
default:
tx.setText("No text");
}
}
};
class Connect extends Thread{
public void run(){
try {
try {
BS.connect();
Log.d("LOG", " e");
Log.d("LOG", "r" + BS.isConnected());
DataTransfer dataTransfer = new DataTransfer();
dataTransfer.start();
}catch(NullPointerException e){
Log.d("LOG", " meezaan");
}
}catch(IOException e){
Log.d("LOG", "t");
}
}
}
class Accept extends Thread{
public void run() {
try {
while (true) {
server = BA.listenUsingRfcommWithServiceRecord("Secure Connection", uuid);
server.accept();
Log.d("LOG", "accept");
}
}catch(IOException E) {
}
}
}
class DataTransfer extends Thread{
#Override
public void run() {
int d = 1;
InputStream receive = null;
Log.d("LOG", "On");
int numBytes;
byte[] buffer = new byte[1024];
try {
receive = BS.getInputStream();
Log.d("LOG", "pn");
while (BS.isConnected()) {
try {
if (d <= 5) {
Log.d("LOG", "did");
++d;
}
numBytes = receive.read(buffer);
handler.obtainMessage(MessageContents.MSG_MESSAGE, numBytes, -1, buffer).sendToTarget();
} catch (NullPointerException e) {
Log.d("LOG", "error read(null)");
}
}
Log.d("LOG", "pnA");
} catch (IOException IOE) {
Log.d("LOG", "error read(IOE)");
}
}
}
public void onOne(View view){
write("1".getBytes());
}
public void onClick(View view){
Button b1 = (Button) findViewById(R.id.button);
EditText pin = (EditText) findViewById(R.id.editText);
pin.setRawInputType(Configuration.KEYBOARD_QWERTY);
pin.setVisibility(View.VISIBLE);
b1.setVisibility(View.VISIBLE);
}
public void pin (View view) {
Button b1 = (Button)findViewById(R.id.button);
EditText pin = (EditText)findViewById(R.id.editText);
String pin1 = pin.getText().toString();
if (pin1.equals("")) {
Connect connect = new Connect();
connect.run();
pin.setVisibility(View.INVISIBLE);
b1.setVisibility(View.INVISIBLE);
} else {
Toast.makeText(getApplicationContext(), "Wrong Pin!"+pin1, Toast.LENGTH_SHORT).show();
pin.setVisibility(View.INVISIBLE);
b1.setVisibility(View.INVISIBLE);
}
}
public void onTwo(View v){
Toast.makeText(getApplicationContext(), "" + handler.hasMessages(MessageContents.MSG_MESSAGE) + " " + BS.isConnected(), Toast.LENGTH_SHORT).show();
}
public void write(byte[] Byte){
try {
OutputStream transfer = BS.getOutputStream();
try {
transfer.write(Byte);
}catch(NullPointerException e){
Log.d("LOG", "error write(null) " + BS.isConnected());}
}catch (IOException IOE){ Log.d("LOG", "b");
Log.d("LOG", "error write(IOE) " + BS.isConnected());}
}
}`
Hi, this is my code. After writing Bytes[] I don't receive anything on second device. When I remove 'numBytes = receive.read(buffer)' handler would work or display
'no text'
I think receive.read(buffer) waits for an input which means write is a problem or receive.read(buffer) is the problem. Please ignore names, logs with random letters in or device names or unnecessary imports or variables. Thank You :) Sorry I did not have time to indent everything. If you are viewing please put something like don't know.Thank you.
I am fairly new to Android, i want to write a telnet client app for my Android. I have written the code using Apache commons library for telnet. Now i am able to connect to telnet server (for that i have used Asyctask concept) and able to read login banner after a long time i don't know what is causing that. I have modified the example given in Apache commons to work with my android code.I have two java codes in my "src" folder (MainActivity.java and TelnetClientExample.java). First, i want to get the login prompt and then i want user to interact with it please help, Thanks in advance :)
I am posting my screen capture of what i am getting.
MainActivity.java
package com.example.telnetapp;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity{
public static int port_int_address;
private EditText server,port;
private Button connect;
public static String ip,port_address;
public PrintWriter out;
public static TextView textResponse;
static String response;
public InputStream instr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
server = (EditText)findViewById(R.id.edittext1);
port = (EditText)findViewById(R.id.edittext2);
connect = (Button)findViewById(R.id.connect);
textResponse = (TextView)findViewById(R.id.response);
connect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ip = server.getText().toString();
port_address = port.getText().toString();
port_int_address = Integer.parseInt(port_address);
try{
MyClientTask task = new MyClientTask(ip, port_int_address);
task.execute();
}
catch(Exception e){Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
TelnetClientExample job;
MyClientTask(String inetAddress, int port){
dstAddress = inetAddress;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
try {
job = new TelnetClientExample();
job.backgroundjob();
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
try {
instr = TelnetClientExample.tc.getInputStream();
byte[] buff = new byte[1024];
int ret_read = 0;
do
{
ret_read = instr.read(buff);
if(ret_read > 0)
{
MainActivity.response += new String(buff, 0, ret_read);
}
}
while (ret_read >= 0);
}
catch (Exception e) {
MainActivity.response += e.toString();
MainActivity.response += "From reading from telnet server ! \n";
}
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
TelnetClientExample.java
package com.example.telnetapp;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.net.telnet.TelnetClient;
public class TelnetClientExample {
public String remoteip = MainActivity.ip;
public int remoteport= MainActivity.port_int_address;
public static TelnetClient tc = null;
public void backgroundjob() throws IOException {
tc = new TelnetClient();
try {
tc.connect(remoteip, remoteport);
}
catch (Exception e) {
}
}
public void close_con(){
try {
tc.disconnect();
}
catch (Exception e) {
MainActivity.response += e.toString();
MainActivity.response += "From reading from disconnecting telnet server ! \n";
}
}
}
The problem is in this code snippet . please look into this and help me to get an interactive session.
protected void onPostExecute(Void result) {
try {
instr = TelnetClientExample.tc.getInputStream();
byte[] buff = new byte[1024];
int ret_read = 0;
do
{
ret_read = instr.read(buff);
if(ret_read > 0)
{
MainActivity.response += new String(buff, 0, ret_read);
}
}
while (ret_read >= 0);
}
catch (Exception e) {
MainActivity.response += e.toString();
MainActivity.response += "From reading from telnet server ! \n";
}
textResponse.setText(response);
super.onPostExecute(result);
}
The problem i am getting -
I have an Android app, which should receive and read NMEA-sentences
e.g. $GPGLL,3751.65,S,14507.36,E*77
from a remote TCP-Server using Telnet protocol. I am using the org.apache.commons.net.telnet.TelnetClient library.
What works:
Connecting to Server
Reading some sentences without any error
Problem:
There are more than half of the sentences missing. I guess that it is a timing problem, perhaps this has also to do with the connection which gets restarted in every iteration.
Here is my MainActivity.java:
package com.example.clienttel;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Go to ClientThread, where NMEA-sentences will be received
int i;
for (i = 0; i < 10000; i++) // 10000 for testing
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
//#Override
public void run() {
TelnetClient telnet = new TelnetClient();
// Variables
String ADDRESS = "194.66.82.11";
int PORT = 51000;
String NMEA = null;
final String TAG = "TestApp";
// Connect To Server
try {
telnet.connect(ADDRESS, PORT);
} catch (IOException e) {
e.printStackTrace();
}
// Process NMEA-sentences
InputStream inStream = telnet.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(inStream));
try {
NMEA = r.readLine();
} catch (IOException e) {
e.printStackTrace();
}
// Ignore "...busy" sentences
if (NMEA != null) {
if(!(NMEA.equals("*** Serial port is busy ***"))) {
Log.i(TAG, NMEA);
}
}
// Disconnect From Server
try {
telnet.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any help would be appreciated!
EDIT:
My code now looks like this:
package com.example.clienttel;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MainActivity extends ActionBarActivity {
// Variables
public String ADDRESS = "194.66.82.11";
public int PORT = 50100;
public String NMEA = null;
public final String TAG = "TestApp";
public boolean first = true;
// Handler in mainthread
Handler handler = new Handler() {
public void handleMessage(Message msg) {
String dataString = "";
Bundle bundle = msg.getData();
Log.d("handleMessage", bundle.toString());
if (bundle.containsKey("outgoingString")) {
dataString = bundle.getString("outgoingString");
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ClientThread ct;
ct = new ClientThread();
ct.mhandler=handler;
int i;
for (i = 0; i < 10000; i++) { // 10000 for testing
// Go to ClientThread, where NMEA-sentences will be received
//new Thread(new ClientThread()).start();
ct.start();
}
}
class ClientThread implements Runnable {
public Handler mhandler = null;
#Override
public void run() {
TelnetClient telnet = new TelnetClient();
if (first) {
// Connect To Server in 1st Iteration
try {
telnet.connect(ADDRESS, PORT);
} catch (IOException e) {
e.printStackTrace();
}
first = false;
}
// Process NMEA-sentences
InputStream inStream = telnet.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(inStream));
try {
NMEA = r.readLine();
} catch (IOException e) {
e.printStackTrace();
}
// Handler in ClientThread to send back
Bundle b = new Bundle();
b.putString("outgoingString", NMEA);
Message m = mhandler.obtainMessage();
m.setData(b);
mhandler.sendMessage(m);
}
}
}
but I am not sure about the placement of the handlers
As #EJP said, opening an closing the connection for each line will kill the app...
A better approach is have the thread handle the communication(s) and wait for the next line, passing the data back to the main thread as a bundle message.
There are plenty of examples out there, but essentially you create a handler in your main thread:
Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
String dataString = "";
Bundle bundle = msg.getData();
Log.d("handleMessage", bundle.toString());
if (bundle.containsKey("outgoingString"))
{
dataString = bundle.getString("outgoingString");
}
// you can handle other message types here....
}
and pass it (the handler) to your ClientThread (here, as mhandler) where you can send the messages back:
Bundle b = new Bundle();
b.putString("outgoingString", outgoingText);
Message m = mhandler.obtainMessage();
m.setData(b);
mhandler.sendMessage(m);
I develop simple client-server app for Android by examples:
http://android-er.blogspot.com/2014/02/android-sercerclient-example-server.html
http://android-er.blogspot.com/2014/02/android-sercerclient-example-client.html
Server code:
package com.example.androidserversocket;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView info, infoip, msg;
String message = "";
ServerSocket serverSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
infoip = (TextView) findViewById(R.id.infoip);
msg = (TextView) findViewById(R.id.msg);
infoip.setText(getIpAddress());
Thread socketServerThread = new Thread(new SocketServerThread());
socketServerThread.start();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 8080;
int count = 0;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
info.setText("I'm waiting here: "
+ serverSocket.getLocalPort());
}
});
while (true) {
Socket socket = serverSocket.accept();
count++;
message += "#" + count + " from " + socket.getInetAddress()
+ ":" + socket.getPort() + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(
socket, count);
socketServerReplyThread.run();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerReplyThread extends Thread {
private Socket hostThreadSocket;
int cnt;
SocketServerReplyThread(Socket socket, int c) {
hostThreadSocket = socket;
cnt = c;
}
#Override
public void run() {
OutputStream outputStream;
String msgReply = "Hello from Android, you are #" + cnt;
try {
outputStream = hostThreadSocket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.print(msgReply);
printStream.close();
message += "replayed: " + msgReply + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message += "Something wrong! " + e.toString() + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
}
Client code:
package com.example.androidclient;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText)findViewById(R.id.address);
editTextPort = (EditText)findViewById(R.id.port);
buttonConnect = (Button)findViewById(R.id.connect);
buttonClear = (Button)findViewById(R.id.clear);
textResponse = (TextView)findViewById(R.id.response);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonClear.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
textResponse.setText("");
}});
}
OnClickListener buttonConnectOnClickListener =
new OnClickListener(){
#Override
public void onClick(View arg0) {
MyClientTask myClientTask = new MyClientTask(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()));
myClientTask.execute();
}};
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
MyClientTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
I work with TWO emulators Android.
When server starts it gets IP: 10.0.2.15
And in Client window I set IP: 10.0.2.15 and PORT:8080.
But I get exception: "Failed to connect to /10.0.2.15 (port 8080): connect failed: ECONNREFUSED (Connection refused)"
Why I can not connect?
Just to recap this as an answer: Testing on a real device should solve the issue. Apps generally have to be tested on at least one (better several) real device. Especially trying to connect an emulator to another emulator on the same PC is not even remotely close to a real situation. One device would be enough for you. That is, a real Android can connect to an emulator or the other way round as long as the PC allows the connection.
I have a working FTP system with android, but I want to be able to track the bytes as they get uploaded, so I can update a progress bar as the upload progresses. Is this possible with Android? Right now, I'm using org.apache.common.net.ftp and the code I'm using is below. Also, I am running this in an AsyncTask.
package com.dronnoc.ftp.complex;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.io.CopyStreamEvent;
import org.apache.commons.net.io.CopyStreamListener;
import org.apache.commons.net.io.Util;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
public class Main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
String text = "BIGFILE"; //Big file here
InputStream data = new ByteArrayInputStream(text.getBytes());
new ComplexFTPTransfer().execute(data);
}
private class ComplexFTPTransfer extends AsyncTask<InputStream, Long[], Void>
{
private FTPClient ftp = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
ftp = new FTPClient();
ftp.connect("hostname");
} catch (SocketException e) {
this.cancel(true);
} catch (IOException e) {
this.cancel(true);
}
Main.this.setProgressBarIndeterminateVisibility(true);
}
#Override
protected Void doInBackground(InputStream... params) {
if(!this.isCancelled())
{
try
{
if(ftp.login("user", "pass"))
{
ftp.enterLocalPassiveMode();
InputStream item = params[0];
int streamSize = 0;
while(item.read() != -1)
{
streamSize++;
}
InputStream is = new BufferedInputStream(params[0], streamSize);
OutputStream os = ftp.storeFileStream("/test.txt");
Util.copyStream(is, os, streamSize, streamSize, new CopyStreamListener() {
#Override
public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
publishProgress(new Long[] {totalBytesTransferred, streamSize});
}
#Override
public void bytesTransferred(CopyStreamEvent event) {
}
});
ftp.completePendingCommand();
}
ftp.logout();
ftp.disconnect();
}
catch (IOException e) {
}
catch (Exception e) {
}
}
return null;
}
#Override
protected void onProgressUpdate(Long[]... values) {
super.onProgressUpdate(values);
Log.d("UPDATE", values[0] + " of " + values[1] + " copied.");
//TODO Put code here
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Main.this.setProgressBarIndeterminateVisibility(false);
}
}
}
What I want to know is if I can run a progress bar, updating every few uploaded bytes?
Cheers
This question has an implementation of an InputStream that includes a progress callback. Use that InputStream and call publishProgress from that callback for incremental updates during the file upload.
Download this .jar file
httpmime-4.1.1.jar and commons-net.jar
try {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(InetAddress
.getByName(Your host Url));
ftpClient.login(loginName, password);
System.out.println("status :: " + ftpClient.getStatus());
ftpClient.changeWorkingDirectory(your directory name);
ftpClient.setFileType(FTP.IMAGE_FILE_TYPE);
//Your File path set here
File file = new File("/sdcard/my pictures/image.png");
BufferedInputStream buffIn = new BufferedInputStream(
new FileInputStream(myImageFile));
ftpClient.enterLocalPassiveMode();
ProgressInputStream progressInput = new ProgressInputStream(
buffIn);
boolean result = ftpClient.storeFile(UPLOADFILENAME + ".png",
progressInput);
System.out.println("result is :: " + result);
buffIn.close();
ftpClient.logout();
ftpClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
//ProgressInputStream
import java.io.IOException;
import java.io.InputStream;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class ProgressInputStream extends InputStream {
/* Key to retrieve progress value from message bundle passed to handler */
public static final String PROGRESS_UPDATE = "progress_update";
private static final int TEN_KILOBYTES = 1024 * 40;
private InputStream inputStream;
//private Handler handler;
private long progress;
private long lastUpdate;
private boolean closed;
public ProgressInputStream(InputStream inputStream) {
this.inputStream = inputStream;
this.progress = 0;
this.lastUpdate = 0;
this.closed = false;
}
#Override
public int read() throws IOException {
int count = inputStream.read();
return incrementCounterAndUpdateDisplay(count);
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
int count = inputStream.read(b, off, len);
return incrementCounterAndUpdateDisplay(count);
}
#Override
public void close() throws IOException {
super.close();
if (closed)
throw new IOException("already closed");
closed = true;
}
private int incrementCounterAndUpdateDisplay(int count) {
if (count < 0)
progress += count;
lastUpdate = maybeUpdateDisplay(progress, lastUpdate);
return count;
}
private long maybeUpdateDisplay(long progress, long lastUpdate) {
if (progress - lastUpdate < TEN_KILOBYTES) {
lastUpdate = progress;
sendLong(PROGRESS_UPDATE, progress);
}
return lastUpdate;
}
public void sendLong(String key, long value) {
Bundle data = new Bundle();
data.putLong(key, value);
Message message = Message.obtain();
message.setData(data);
//handler.sendMessage(message);
}
}
This can be done using Secure FTP Factory library.
You just need to implement an instance of the com.jscape.inet.ftp.FtpListener interface, register the instance with the Ftp class and overload the progress(FtpProgressEvent event) method to capture progress information.
JavaDoc: Overview (secure FTP Factory API)
Download: Java FTP, Java FTPS and Java SFTP Components