when started, my android application loads some image from a remote server using an Asynchronous task. Sometimes, when the connection is too weak, it takes a long time to load and it's not great.
how can i add timeout to this task, so that if the activity can't load the images after 10 seconds for example, the user will get an error message
use AsyncTask and then show the progress bar for 10 seconds. if it exceeds more than that 10 sec show the log message .
AsyncTask
You can try something like this
private static final int MAX_ATTEMPTS = 5;
static class Task extends AsyncTask<String, Integer, Integer> {
protected Integer doInBackground(String... vals) {
try {
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to server connection");
try {
//DO STUFF
} catch (IOException e) {
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return 400;
}
// increase backoff exponentially
backoff *= 2;
}
}
} catch (Exception e) {
Log.e(TAG, "ERROR", e);
}
return 400;
}
protected void onPostExecute(Integer success) {
}
}
But I suggest you look at Volley, Google's new networking library. That will serve you best. I use this code above in one of my upload methods
if you are using .net web services for get data from server then use below:
HttpTransportSE aht1 = new HttpTransportSE(URL, 60000);
Where, URL is your connection url of webservices. here, it waits for 1 minute for get response. after that it throws error of timeout.
Related
Im trying use use an AMQP message queue in one of my Android applications. I tested the code first in a java application and have no issues but when I put the same code into an Android app no error is thrown but the AMQP channel closes unexpectedly after the first message is received. I tried adding a shutdown listener to the channel but it didnt return anything. Can someone help me figure out why the Rabbitmq channel is closing?
// ------------------------------------------------------------------------
// Function to make AMQP connection and subscribe
// ------------------------------------------------------------------------
int connAmqp()
{
factory = new ConnectionFactory();
factory.setHost(PI_AMQP_BROKER_URL);
factory.setUsername(AMQP_BROKER_USERNAME);
factory.setPassword(AMQP_BROKER_PASSWORD);
factory.setPort(AMQP_BROKER_PORT);
connection=null;
connectionStatus = AMQP_CONNECTING;
try {
connection = factory.newConnection();
Log.i("log_amqp_conn","Successfully connected to AMQP broker");
connectionStatus = AMQP_CONNECTED;
channel = connection.createChannel();
channel.addShutdownListener(new ShutdownListener() {
#Override
public void shutdownCompleted(ShutdownSignalException cause) {
Log.w("log_amqp_shutdown",cause.getCause().toString());
}
});
channel.exchangeDeclare(AMQP_EXCHANGE_NAME, "topic");
Log.i("log_amqp_conn","Successfully connected to Exchange: " + AMQP_EXCHANGE_NAME);
channel.queueDeclare(RX_QUEUE_NAME, false, false, false, null);
String queueBind = RX_BINDING;
Log.i("log_amqp_conn","Successfully declared queue: " + RX_QUEUE_NAME);
channel.queueBind(RX_QUEUE_NAME, AMQP_EXCHANGE_NAME, queueBind);
Log.i("log_amqp_conn","Successfully binding to: " + queueBind);
} catch (TimeoutException e) {
Log.i("log_amqp_conn","Connection timeount - Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_TIMEOUT;
} catch (IOException e) {
Log.i("log_amqp_conn","Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_UNKNOWNREASON;
}catch (Exception e) {
Log.i("log_amqp_conn","Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_UNKNOWNREASON;
}
Log.i("log_amqp_conn"," [*] Waiting for messages.");
consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
Log.i("log_amqp_conn", "handleDelivery() called");
String message = new String(body, "UTF-8");
Log.i("log_amqp_conn"," [Rx] Received: " + message);
//DO SOME WORK HERE
}
};
try {
Log.i("log_amqp_conn", "basicConsume() called");
channel.basicConsume(RX_QUEUE_NAME, true, consumer);
} catch (IOException e) {
Log.e("log_amqp_consume",e.toString());
}
return 0;
}
After spending much time looking in the wrong places I found that the channel was closing due to an unhandled exception in the handleDelivery() function in the "//DO SOME WORK HERE" code. Turns out that if this method errors out that the AMQP channel will close. Thanks.
I am facing a problem in checking of internet speed. Actually I am developing an android app which can test your internet speed on your cell phone. I make an sample to test the speed and its show write speed such as 7.3 Mbps as I am getting from my ISP. But in this test I am using below code.
long startCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "start conn = " + startCon);
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(imageURL);
HttpResponse response = null;
try {
response = httpClient.execute(httpGet);
Log.i("SketchEffect","Executing http connection to download selected image.");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
}
long endCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "endCon = " + endCon);
Now I want to show progress as of internet speed by using a handler and using different method download a file.'
In this method I am using below code
String downloadFileUrl = "http://www.gregbugaj.com/wp-content/uploads/2009/03/dummy.txt";
URL url1 = new URL(downloadFileUrl);
URLConnection con1 = url1.openConnection();
con1.setUseCaches(false); stream1 = con1.getInputStream();
Message msgUpdateConnection = Message.obtain(mHandler,
MSG_UPDATE_CONNECTION_TIME);
msgUpdateConnection.arg1 = (int) connectionLatency;
mHandler.sendMessage(msgUpdateConnection);
long start = System.currentTimeMillis();
int currentByte = 0;
long updateStart = System.currentTimeMillis();
long updateDelta = 0;
int bytesInThreshold = 0;
int bytesIn = 0;
while (true) {
if ((currentByte = stream1.read()) == -1) {
break;
} else {
bytesIn++;
bytesInThreshold++;
baf.append((byte) currentByte);
if (updateDelta >= UPDATE_THRESHOLD) {
int progress = (int) ((bytesIn / (double) EXPECTED_SIZE_IN_BYTES) * 100);
Message msg = Message.obtain(mHandler,
MSG_UPDATE_STATUS,
calculate(updateDelta, bytesInThreshold));
msg.arg1 = progress;
msg.arg2 = bytesIn;
mHandler.sendMessage(msg);
// Reset
updateStart = System.currentTimeMillis();
bytesInThreshold = 0;
}
updateDelta = System.currentTimeMillis() - updateStart;
}
} if (downloadTime == 0) {
downloadTime = 1;
}
Message msg = Message.obtain(mHandler, MSG_COMPLETE_STATUS,
calculate(downloadTime, bytesIn));
msg.arg1 = bytesIn;
mHandler.sendMessage(msg);
By above code I am getting only .8 or 1.o Mbps speed (In mega bit per secons not bytes)
i'm trying to do the same thing, using a HTTP GET to measure Internet Speed (download), but there is a problem. When you do this: response = httpClient.execute(httpGet); you are not measuring only the time that takes for you to receive the answer, you are measuring the time that takes to make the entire request, that means that you are measuring the overhead of the entire protocol like establishing the TCP connection between server and client.
Check this: http://tinypic.com/r/15u6og/8
The useful data that you want are the PDU's, the rest is just overhead. But you are measuring the entire thing. As you can see establishing the TCP connection takes a lot of time.
That's why you are getting a wrong value.
I know this is a little late, but have you resolved this yet?
i wrote a Server for our global Leadbord which actually works now.
I can send data to it if it's active. But if it's down my app does not stop. I dont get a solution for it i hope you can help me. Here is the sending:
public void saveToDatabase(LeadboardElement element2) {
final LeadboardElement element = element2;
send = false;
// Need to be a thread! else android blocks it because it could take to
// long to send!
this.thread = new Thread() {
public void run() {
try {
Socket soc = new Socket(Config.TCP_SERVERNAME_IP,
Config.TCP_PORT);
DataOutputStream out = new DataOutputStream(
soc.getOutputStream());
DataInputStream in = new DataInputStream(
new BufferedInputStream(soc.getInputStream()));
// to call the save statement!
out.writeInt(0);
// give the stuff
out.writeUTF(element.getName());
out.writeInt(element.getLevel());
out.writeInt(element.getKillPoints());
// close it
out.close();
in.close();
soc.close();
send = true;
//join at every error
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
};
// start it
thread.start();
// join thread
if (!send) {
boolean retry = true;
while(retry)
try {
this.thread.join();
retry = false;
Log.w(TAG, "sending to server stopped!");
} catch (InterruptedException e2) {
Log.w(TAG, "Thread could not be joined");
}
}
}
I noticed that i need to do it in a thread since API 5 so it works like this. It's called at the end of an Game if the player touches the screen. Everything get stopped and the data is sent to the Server. If hes down it does not work we stuck in the fade to black.
I guess i need something like a timeout. I tried it with a CountDownTimer but this acutally does not solve the problem.
Thanks alot!
Changing the way you initialize the socket, you can set a timeout.
Socket s1 = new Socket();
s1.setSoTimeout(200);
s1.connect(new InetSocketAddress("192.168.1." + i, 1254), 200);
Add a timeout when creating a new Socket
In my application I need to scan the local subnet (192.168.1.*) to collect the list of MAC addresses of all connected devices.
I currently use the following strategy:
start simultaneously 255 ping commands with Runtime.exec("ping -c 1 <addr>")
use waitFor() on each of the returned process to collect the exit code
close input streams of processes and destroy them
read the /proc/net/arp file and parse the MAC addresses
In most cases, this works very well and provides a fast scan.
But on some devices (such as android 1.5, and sometimes on >=4.0), the execution gets stuck at process creation (after a few ones have been successfully started) and there's no way to kill the running thread.
Do you see anything I could try to solve this issue? Or any other strategy that would not take too long?
This can be solved by using a pool of thread running the INetAddress.isReachable() method (instead of running the ping command in native processes).
private static final int NB_THREADS = 10;
public void doScan() {
Log.i(LOG_TAG, "Start scanning");
ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS);
for(int dest=0; dest<255; dest++) {
String host = "192.168.1." + dest;
executor.execute(pingRunnable(host));
}
Log.i(LOG_TAG, "Waiting for executor to terminate...");
executor.shutdown();
try { executor.awaitTermination(60*1000, TimeUnit.MILLISECONDS); } catch (InterruptedException ignored) { }
Log.i(LOG_TAG, "Scan finished");
}
private Runnable pingRunnable(final String host) {
return new Runnable() {
public void run() {
Log.d(LOG_TAG, "Pinging " + host + "...");
try {
InetAddress inet = InetAddress.getByName(host);
boolean reachable = inet.isReachable(1000);
Log.d(LOG_TAG, "=> Result: " + (reachable ? "reachable" : "not reachable"));
} catch (UnknownHostException e) {
Log.e(LOG_TAG, "Not found", e);
} catch (IOException e) {
Log.e(LOG_TAG, "IO Error", e);
}
}
};
}
Situation: I would like to pull a network resource (a file), display it for 30 seconds, then load the next file. While displaying the initial file for 30 seconds, I'd like to preload the next file.
Question: Should I be using concurrent threads with a lock (like a linked blocking queue?) or a handler? Or something I'm missing?
Currently I have the onCreate call an asynctask that has a for loop which iterates through an array of paths for the files one at a time, which then calls the next asynctask (inside the for loop) which downloads the file from that path and then in the onPostExecute assigns the file to the UI view.
This works but I am unable to setup timing where the first file loads in the UI view then 30 seconds later the next file loads in the UI view and so on... Right now it loads the files fine but the 1st may take 40 seconds to display and the 2nd 25 seconds and the 3rd 60.
(FYI, the files are uniform size and only take 5~15 sec to load)
Here's a general example (non compile-able):
onCreate(){
new firstAsynchTask().execute(filePaths[]);
}
private class firstAsynchTask extends AsyncTask<String[], Void, Void> {
protected Void doInBackground(String[]... x) {
try {
for(int i = 0; x[0] != null && i < x.length; i++)
{
long startT = System.currentTimeMillis();
if(x[0][i].isFile())
{
SmbFile g = new SmbFile(x[0][i].getPath());
new secondAsynchTask().execute(g);
long TimeNow = (System.currentTimeMillis() - 30000);
if(startT > TimeNow)
{
try {
Thread.sleep(startT - TimeNow);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();}
}
}
if(i == x.length - 1)
{
i = 0;
}
}
return null;
} catch (IOException e) {
// TODO Auto-generated catch block
return null;
}
}
private class SecondAsyncTask extends AsyncTask<File, Integer, Drawable> {
protected File doInBackground(File... x) {
SomeType FileTemp = new File();
try {
long startT = System.currentTimeMillis();
FileTemp = (get streamed file);
long TimeNow = (System.currentTimeMillis() - 30000);
if(startT > TimeNow)
{
Thread.sleep(startT - TimeNow);
return FileTemp;
}
else
{
return FileTemp;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
protected void onPostExecute(File result) {
if(result != null)
{
FileView centerFile = (FileView) findViewById(R.id.FileView1);
centerFile.setFile(result);
}
}
}
It looks like a simple producer-consumer approach would be sufficient for what you need. I would have an array of URLs that point to your network resource with a synchronised access. A single AsyncTask would be enough to pop a single URL off the queue, download and display it. How you will re-invoke the task depends on you: you can display downloaded resource and at the same time run task, putting downloaded resource to some temporary placeholder (a Drawable member field for example). Have a timer that every 30 seconds just puts temporary resource to the display and runs download/cache task again.
Of course this is a very simple solutions without handling cases when your task haven't finished in 30 seconds time frame, etc.
Another approach would be to have a boolean object that you will set to true every 30 seconds. Your AsyncTask runs, downloads image and on onPostExecute checks if previously mentioned boolean is set to true, if yes - displays image, sets flag to false and finishes. If flag is false then it enters a loop that sleeps for, say, 200ms and checks condition again, etc.