public Object fetch(String address) throws MalformedURLException,
IOException {
URL url = new URL(address);
Object content = url.getContent();
return content;
}
private Drawable ImageOperations(Context ctx, String url) {
try {
InputStream is = (InputStream) this.fetch(url);
Drawable d = Drawable.createFromStream(is, "src");
return d;
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
catch (Exception e)
{
return null;
}
}
try {
Drawable a =ImageOperations(this,"url"); imgView.setImageDrawable(a);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
This works, but on rare ocasions the app freezes due to a "SocketException: Adress family not supported by protocol". Is there any way to fix this? Thanks
You are trying to Download a File from the UI Thread...(which is why your UI Freezes)
Use a Seperate Thread or AsyncTask so that your UI doesn't Freeze up.
This should solve your problem.
As st0le has pointed out you are trying to do the heavy duty stuff from the UI thread.
All heavy-duty stuff in Android should be done on other worker thread. Because doing it in main thread (or the UI thread) can make your application unresponsive and may be killed as the system is persuaded to think that it has hung.
So you have to do the long running operations in separate thread. For implementing this you can use the concept of Handlers.
Related
I made android application that connects to remote server and send some data.
Remote server is Windows application.
Connection method:
private void ConnectToMonitor() {
try {
s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This works perfectly if server is online. Application is sending data and server is receiving. But if server is offline android app. is blocked. My question is how to handle this? How to continue with application and avoid error even the server is down?
Remember to call this outside the UIThread.
Follow this tutorial. In android all connections need to be managed outside the UIThread, in the tutorial I linked you will find easy ways to post your results back to the UI (handlers, asynctasks...)
Of course we don't know if the problem is about the thread with just the given code, but it is the most usual error.
First remember to set the socket timeout :
mSocket.setSoTimeout(timeout); //in milliseconds
You can however specify different timeout for connection and for all other I/O operations through the socket:
private void connectToMonitor() {
try {
socket = new Socket();
InetAddress[] iNetAddress = InetAddress.getAllByName(SERVER_ADDRESS);
SocketAddress address = new InetSocketAddress(iNetAddress[0], TCP_SERVER_PORT);
socket.setSoTimeout(10000); //timeout for all other I/O operations, 10s for example
socket.connect(address, 20000); //timeout for attempting connection, 20 s
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Second, in Android, you should perform any network I/O in separate threads!
As an example, using regular Java Threads :
String threadName = getClass().getName() + "::connect";
new Thread(new Runnable() {
#Override
public void run() {
connectToMonitor();
}
}, threadName).start();
You can set A timeout for the socket. Use Socket.setSoTimeout method
socket.setSoTimeout(timesinmilis);
by using this your socket will throw a socket timout exception. You can catch that and do what you want
Below is the receive method that implements a socket server and works perfectly.
private void Receive(){
log.info("Server started - waiting for the clients.");
try {
Boolean end = false;
ServerSocket ss = new ServerSocket(12345);
while(!end){
//Server is waiting for client here, if needed
Socket s = ss.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter output = new PrintWriter(s.getOutputStream(),true); //Autoflush
String st = input.readLine();
JSONObject jsonObj;
try {
jsonObj = new JSONObject(st);
long id = jsonObj.optLong("DeviceID", count.addAndGet(1) );
String name = jsonObj.toString();
table.put(id, name);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
etResult.setText(st);
Log.d("Tcp Example", "From client: "+st);
output.println("Response from Sever: Connectivity ok");
s.close();
if (st != null ){ end = true; }
}
ss.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The only problem is, when I hit the button to call that method, the socket starts listening and waits for a client messages. While it does not happen, the app remains freezes and I try to hit any other button, the app may crashes.
Does anyone have a hint about how could handle it and leave the socket listening in "background" withou locking the entire screen?
thank you
Make a thread or AsyncTask and do all the socket functions on that. IF it's something you're going to rarely do and want to fire it off and process the results, use an AsyncTask. If it's something you're going to want to do constantly and don't want to run multiple workers at the same time or have multiple workers queued up, use a Thread.
I'm getting the following errors in the code below: The return type is incompatible with AsyncTask.onPostExecute(Integer). I'm trying to return the result from the http request done in the doInBackground task. I get the error: Type mismatch: cannot convert from AsyncTask to int in the return statement for isAvailable. I feel like there's something simple I'm not doing but I can't quite figure it out.
public int isAvailable(int position) {
GetIsAvailable isAvail = new GetIsAvailable();
Integer nisAvail = isAvail.execute(position); // error is still here
return nisAvail;
}
private class GetIsAvailable extends AsyncTask<Integer,Void,Integer > {
#Override
protected Integer doInBackground(Integer...position) {
Bundle resBundle = new Bundle();
String url = "http://www.testurl.com"
+ position[0]+"&uname="+AppStatus.mUserName;
URL iuri;
try {
iuri = new URL(url);
URLConnection connection = iuri.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-type",
"application/x-www-form-urlencoded");
BufferedReader br = new BufferedReader(new InputStreamReader(
(InputStream) connection.getContent()));
resBundle.putInt("isAvail", Integer.parseInt(br.readLine().trim()));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new Integer(0);
}
#Override
protected Integer onPostExecute(Integer isAvail) { // Main Error here
return isAvail;
}
Oh, I think I see the problem. I don't think you can handle this the way you're doing it currently. You should be handling the effects of the value of isAvail within the onPostExecute() method. isAvailable() is running on the main thread, while isAvail is running on a separate thread. You're trying to return the result of the AsyncTask before it has finished completion.
I'm 99% sure that's the problem.
I believe what you're looking for is
Integer nisAvail = isAvail.execute(position).get();
but then the task is no longer asynchronous as the UI thread has to wait until the AsyncTask finishes.
If you want to keep it asynchronous then you have to handle the result in onPostExecute.
This return an int:
return Integer.parseInt(br.readLine().trim());
this return an int as well:
return 0;
You must return an Integer:
return new Integer(br.readLine().trim());
return new Integer(0);
If you want to get value returned from doInBackground method.
Then do this:
Integer Value = AsyncTaskClass.execute(ParamsIfSpecified).get();
I am working with Android Facebook SDK and wanted to get a friends list. I have created an "AsyncTask" for doing such a thing. I am pasting my doInBackgroundMethod here.
#Override
protected String doInBackground(String... url) {
String jsonResponse;
try {
jsonResponse = Factory.getFacebook().request(Utils.LOGGEDIN_USER_FRIENDS);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
return jsonResponse;
}
Utils Code
public static final String LOGGEDIN_USER_FRIENDS = "me/friends";
The problem I am running in to is that it is returning an empty jsonResponse for the first time the application runs. When I open my app the second time I am getting the JsonResponse. But for the first time however I am getting empty jsonResponse.
Can any one help me out in this regard.
Well it was easy... It was messed up by creating a String variable in a Factory. Later on, the same day I saw that, and called the AsyncTask built in method get which provides the result in the same thread.
I am having a customized list view in my application, which is showing an image and text.
The Image I am getting from URL, using the code below:
private static Drawable ImageOperations(Context ctx, String url,
String saveFilename) {
try {
InputStream is = (InputStream) fetch(url);
Drawable d = Drawable.createFromStream(is, "src");
return d;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static Object fetch(String address) throws MalformedURLException,
IOException {
URL url = new URL(address);
Object content = url.getContent();
return content;
}
all is working perfect, except the list view scrolling, its very slow. If I disable the images, the scroll speed smooth-ens , but with the image enabled, it lags alot.
Is there any possible way I can reduce or remove this lagging?
Thanks
You need to do your fetching in the background.
One of the examples you can use :
http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
use this library for downloading images in background and caching..
it won't hurt the UI
https://github.com/koush/UrlImageViewHelper
Are you lazy loading your images? See this question for details.