I created an Android project on 2.3.3 and tried it on mobile 2.3.3, everything works OK. It didn't work on mobile 4, so I re-built for Android 4, but I have the same problem.
This is the code:
public void FTP_Download(){
String server = "192.168.1.135";
int port = 21;
String user = "pc1";
String pass = "1551";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
Toast.makeText(getBaseContext(), "download starting.",Toast.LENGTH_LONG).show();
// APPROACH #1: using retrieveFile(String, OutputStream)
String remoteFile1 = "i.xml";
File downloadFile1 = new File("sdcard/i.xml");
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
if (success) {
Toast.makeText(getBaseContext(), "File #1 has been downloaded successfully.",Toast.LENGTH_LONG).show();
}
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Note:
I use commons-net-3.1 to connect.
In android version 2.3 above you can not start internet connection from main UI thread. Instead you should use AsyncTask. I assumed you are not using AsyncTask. If you are, then post the code and log cat also. Some examples of other operations that ICS and HoneyComb won't allow you to perform on the UI thread are:( from link posted in comment below ) -
Opening a Socket connection (i.e. new Socket()).
HTTP requests (i.e. HTTPClient and HTTPUrlConnection).
Attempting to connect to a remote MySQL database.
Downloading a file (i.e. Downloader.downloadFile()).
You should not use the main UI Thread to start a network connection or read/write data from it as #phazorRise explained it. But I strongly disagree with using an AsyncTask to perform your download. AsyncTask have been designed for short living operations and downloading a file doesn't belong to that category.
The most relevant way to achieve your goal, if your files are big (and I assume it depends on users, so we can say they are big) is to use a service to download the files.
I invite you to have a look at RoboSpice, it will give your app robustness for networking and it's really the most interesting library for network requests on Android.
Here is an inforgraphics to get familiarized with alternatives and understand why using a service is better than any other technology.
When I use "internet conections" programming for andoid 4, I do an Async Task as follows:
You can put this Class code into the same file as principal file to intercatue with global variables or functions.
public class MyAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String url = urls[0]
try {
//Connection request code, in your case ftp
} catch (Exception e) {
//Catch code
}
}
#Override
protected void onPostExecute(String result) {
//Code to de After the connection is done
}
}
Then, in the Activity I call the Asyn Task
String url = "http://...";
new MyAsyncTask().execute(url);
Edit
Here it's explained how to use Async Task, with an example
http://developer.android.com/reference/android/os/AsyncTask.html
I added this code, and all thing OK
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Note: I taked the code from #user1169115 comment in another post.
This isn't the best soluation, but I don't know why asynctask isn't work, so I don't have another choice.
Related
I'm programming an app with my brother, and today unfortunately, I encountered with a problem.
When the app load a php page via my asynctask class it works fine. but I would like to program this situation: if the remote server is down, or crash, and doesnt display the right page, the application will show error message. but instead, the app crashes =[
I tried to load this page, for example:
http://alonadoni.com/sql3.php
(I want to simulate that there is a problem with the server. the regular page is sql2.php and it works fine when the server works)
When the app try to load this page (sql3.php) , the app crashes.
I did another experiment : I created a file sql3.php, and wrote "aaaaaaaa" in the page, the app doesn't crash in this situation. it downloaded the data "aaaaa". in this case, the app show jsonexecption error.
Unfortunately, I can't get logcat because my old computer can't run emulators, and my phone also can't connect to my computer on developer mode =[ When I try application I create an apk then transfer the file to my phone and install.
my code is:
in OnCreate:
String serverURL = sss() + "sql3.php?imei=" + imei;
new LongOperation().execute(serverURL);
outside OnCreate:
private class LongOperation extends AsyncTask<String, Void, Void> {
private final HttpClient Client = new DefaultHttpClient();
private String Error = null;
protected void onPreExecute() {
}
protected Void doInBackground(String... urls) {
try {
HttpGet httpget = new HttpGet(urls[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
data[x] = Client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
Error = e.getMessage();
Toast.makeText(getApplicationContext(),"error2" , Toast.LENGTH_LONG).show();
cancel(true);
} catch (IOException e) {
Error = e.getMessage();
Toast.makeText(getApplicationContext(),"error34" , Toast.LENGTH_LONG).show();
cancel(true);
}
return null;
}
public void onPostExecute(Void unused) {
if (Error != null) {
} else {
try {
JSONObject json = new JSONObject(data[x]);
name = json.getString("name");
} catch (JSONException e) {
Toast.makeText(getApplicationContext(),"e" + e, Toast.LENGTH_LONG).show();
}
}
x++;
}
}
DoInBackground of asynctask needs to contain only NON UI work , hence referring to context and performing UI operations in UI thread may cause crash.
You can perform UI operations in postexecute of asynctask.
Hence Removing toast from above code which refers to UI operation will solve your issue
AsyncTask works fine in Android 4.x, but not for Android 2.3.6. I've step-by-step debugged Android 2.3.6 with a physical mobile device.
It hangs on here:
myTask = new GetDataFromServer();
GetDataFromServer is the class of AsyncTask.
What's going on?
Here under is my code, I only used 1 AsyncTask in my code and received messages from server.
that's all.
class GetDataFromServer extends AsyncTask<String, String, String>
{
protected void onPreExecute ()
{
progressDialog1=ProgressDialog.show(MainActivity.this, "Loading data", "Please wait...",true);
}
protected String doInBackground(String... params)
{
String resulttxt="";
try {
serverIp = InetAddress.getByName("192.168.1.123");
int serverPort=31000;
Socket clientSocket=new Socket(serverIp,serverPort);
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
bw.write(params[0]);
bw.flush();
BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
resulttxt=br.readLine();
if(resulttxt.contains("OK"))
{
publishProgress(resulttxt);
}
else
{
publishProgress(resulttxt);
clientSocket.close();
bw.close();
br.close();
return null;
}
resulttxt="";
resulttxt=br.readLine();
resulttxt=resulttxt.trim();
clientSocket.close();
} catch (IOException e) {
if(Status_txt!=null)
Status_txt.append( "Server is done.");
}
catch (NetworkOnMainThreadException e){
if(Status_txt!=null)
Status_txt.append( "NetworkOnMainThreadException");
}
return resulttxt;
}
protected void onProgressUpdate(String...inStr){
String[] strData=inStr[0].split("_");
String szTemp="Last Purchase Date: ";
szTemp+=strData[1];
szTemp+=" ,Valid days: ";
szTemp+=strData[2];
//Status_txt.setText(szTemp);
if(Status_txt!=null)
Status_txt.setText("You Are The Super User");
}
protected void onPostExecute(String data) {
tl_prediction2.removeAllViews();
if (data == null)
{
}
else {
if((data.contains("#")==true) || (data.contains("*")==true)
||data.contains("&")==true)
{
String[] arrayTmp=data.split("#");
for(Integer i=0;i<arrayTmp.length;i++)
{
String[] SubArrayTmp=arrayTmp[i].split("_");
tl_prediction2.addView(generateRow(4,SubArrayTmp));
}
}
}
progressDialog1.dismiss();
}
};
Since you haven't posted any code, I could only give you some random probable solutions:
May be your AsyncTask is taking a lot of time to download. Trying increasing its priority using android.os.Process.setThreadPriority(9) inside doInBackground()
Check if you have other previous running long AsyncTask in your code. AsyncTask by default operates on a single background thread. That means your AsyncTask task wouldn't be executed unless your previous AsyncTask are done. To allow parallel execution use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params). You can read more here
Check for Internet and other permissions in Manifest. This is mostly where people make mistake.
AsyncTask works with ThreadPool. If there too many synctasks are executing, the later AsyncTask will be blocked by others. I think you can use the thread tool in DDMS to check the How many ayncTasks are executing.
I'm porting some of my Windows Phone 7 apps to Android. When we call services in the WP7 world, the calls are async. We call the service and there is a delegate _completed event that triggers when when the result is returned. Meanwhile we go on about our way.
The java android code pasted below is how I am calling an HTTP service on my cloud server. I developed this code by going through Android tutorials teaching how to call a service in the android world. Apparently, service calls here are synchronus so the instruction starting with InputStream in... doesn't get executed until the result is returned.
Is this how it is supposed to work for Android? If the service does not respond, there is a wait of a couple minutes and then a timeout exception takes place. That's no good. Everything will hang.
What is the reccommended way to call services in android?
Thanks, Gary
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HttpURLConnection urlConnection = null;
try
{
URL url = new URL("http://www.deanblakely.com/REST/api/products");
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
String myString = readStream(in);
String otherString = myString;
otherString = otherString + " ";
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
urlConnection.disconnect();
}
}
Is this how it is supposed to work for Android?
Yes. Do HTTP operations in a background thread, such as the one supplied by an AsyncTask.
If the service does not respond, there is a wait of a couple minutes and then a timeout exception takes place. That's no good. Everything will hang.
You can set a socket timeout to be something shorter than "a couple minutes". For example, you can call setReadTimeout() on your HttpURLConnection to specify a timeout period in milliseconds.
Im having some trouble reading/writing to a tcp server for which im building an app. In a recent thread I was suggested to use a service instead but this is a project for school which suggested asyncTask so I might aswell go for that.
So the classes ive got are my activity class and async, nothing interesting is going on in activity but sending a string which is working so ill get on with the async one.
class ServerTask extends AsyncTask<Void, Void, Void>{
public static String ip = "10.0.2.2";
public static int port = 2002;
Socket socket;
public DataInputStream dis;
public DataOutputStream dos;
public String message;
#Override
protected Void doInBackground(Void... params) {
try {
socket = new Socket(ip, port);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
Log.i("AsyncTank", "Cannot create Socket");
}
while(socket.isConnected()){
read();
}
}
}
return null;
}
public void write(String message) {
try {
if (socket.isConnected()){
dos.writeUTF(message);
dos.flush();
} else {
Log.i("AsynkTask", "Socket appears to be closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "Writing failed");
}
}
public String read() {
try {
if (socket.isConnected()) {
message = dis.readLine();
} else {
Log.i("AsyncTask", "Cannot read");
}
} catch (Exception e) {
Log.i("AsyncTask", "Cannot read from stream");
}
return message;
}
}
Things I do know, the server DOES get the messages but it doesnt update until I restart the server which leads me to believe that im not pushing a new line or something which makes it all appear as one line after its closed. This however might aswell be the server for which im not reponsible so ill have to read up in that.
The read part however does not want to work, im not sure on how to call the method to have it constantly listen and react to the servers sockt? I tried make a thread just before the return in doInBackGround but then the application starts works for a couple of seconds the force closes due to lack of memory? Do I need a thread to keep constantly listen?
The whole point of this as you might guess is to make a chat so the read method is eventually supposed to update a textView in my activity class. The send method is "working" but not as it should though this might be as I said earlier the server doing some funky buisness.
Another one, is it even possible to have the read as a method like I have or does something have to react when the server sends data and then call the method?
Edit
I have now moved the read part, or atleast some of it to doInBackGround so its now
dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
message = dis.readLine();
Log.i("AsynkTask", "Read : "+message+" this is doInBackGround!");
This along with a change to simply hardcode a printline in the server made me read that line in the client so im guessing its working realtively good for now.
How is it looking? Is it utter crap this code and should be done some other way? Got my functionality but never bad to learn to do it better so to speak :).
You should do both your writing and reading to the Socket in an AsyncTask's doInBackground() method, as both take time and could block the main (UI) thread. I don't know how you are calling your write() method above but you might also want to take a look at this question that might be related.
I have an application in which there is Google map, location overlays on Google map and a separate thread which send the current location of device to server after every 30 seconds. The problem is that when the thread sends the location to server the screen of device halted until the server respond. Here is the following code,
Global Object
private Handler handlerTimer = new Handler();
In onCreate Method
handlerTimer.removeCallbacks(taskUpdateStuffOnDialog );
handlerTimer.postDelayed(taskUpdateStuffOnDialog , 100);
And here is the taskUpdateStuffOnDialog
private Runnable taskUpdateStuffOnDialog = new Runnable()
{
public void run()
{
try
{
URL url3 = new URL("http://"+ appState.getURL()+"//iLocator/IDForClient.php?reg_no="+ Device_ID[0]);
HttpURLConnection conn = (HttpURLConnection) url3.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String quote = reader.readLine();
while (quote != null)
{
Device_ID = quote.split("\n");
quote = reader.readLine();
bCheckID = true;
}//End While
positionOverlay.setID(Device_ID[0]);
addEvent(Device_ID[0]);
}//End try
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(MainMapActivity.this, "Communication Issue",Toast.LENGTH_LONG).show();
}//End catch
handlerTimer.postDelayed(this, 9000);
}
};
Please tell me what is wrong with my code.
The problem is that, although you're spawning a new Thread, you aren't spawning a new process. Everything you're doing is still in the user interface process, and that's blocking. You can find more information on the topic on developer.android.com.
The quickest and easiest way to get around this is using the IntentService class. It will only allow one HTTP request to be executed at a time, but will take care of all the problems for you.
Try using the AsyncTask for connecting to the Server. See an example here: http://developer.android.com/reference/android/os/AsyncTask.html