0

I am trying to upload via FTP a file in a set directory. The file is called "advancedsettings.xml".

The code works fine when used in the Async Task of an Activity, but when attempting to use a Service to carry out the exact same operations within an Async Task, the application crashes with the following error(s):

01-13 16:21:08.403 21134-21151/com.name.example.xx E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1 Process: com.name.example.xx, PID: 21134 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:300) at java.util.concurrent.FutureTask.finishCompletion(F utureTask.java:355) at java.util.concurrent.FutureTask.setException(Futur eTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.jav a:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTas k.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841) Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.(Handler.java:200) at android.os.Handler.(Handler.java:114) at android.widget.Toast$TN.(Toast.java:388) at android.widget.Toast.(Toast.java:114) at android.widget.Toast.makeText(Toast.java:273) at com.name.example.xx.MyService$FTPUpload.doInBackgr ound(MyService.java:58) at com.name.example.xx.MyService$FTPUpload.doInBackgr ound(MyService.java:55) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.jav a:237) ************at android.os.AsyncTask$SerialExecutor$1.run(AsyncTas k.java:231) ************at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1112) ************at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587) ************at java.lang.Thread.run(Thread.java:841) 01-13 16:21:08.473 862-862/? W/ContextImpl﹕ Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1505 com.android.server.analytics.data.collection.appli cation.CrashAnrDetector.broadcastEvent:296 com.android.server.analytics.data.collection.appli cation.CrashAnrDetector.processDropBoxEntry:254 com.android.server.analytics.data.collection.appli cation.CrashAnrDetector.access$100:60 com.android.server.analytics.data.collection.appli cation.CrashAnrDetector$1.onReceive:102 01-13 16:21:08.713 862-21154/? E/android.os.Debug﹕ !@Dumpstate > sdumpstate -k -t -z -d -o /data/log/dumpstate_app_error

Here is how I call the service from within my main activity (on button click):

Intent inetnt=new Intent(FileChooser.this, MyService.class);
        startService(inetnt);

And here is the Service code:

public class MyService extends Service {

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();
    Toast.makeText(MyService.this, "service start", Toast.LENGTH_LONG).show();
    new FTPUpload().execute();

}

@Override
public void onDestroy() {
    super.onDestroy();


}

@Override
public void onLowMemory() {
    super.onLowMemory();

}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    return super.onStartCommand(intent, flags, startId);

}

public class FTPUpload extends AsyncTask<Void, Void, Void> {
    protected Void doInBackground(Void...params) {

        Toast.makeText(MyService.this, "Service FTP Upload Start", Toast.LENGTH_LONG).show();

        FTPClient con = null;

        try

        {
            con = new FTPClient();
            con.connect("host");

            // Check your USERNAME e.g myuser@mywebspace.com and check your PASSWORD to ensure they are OK.
            if (con.login("username", "password")) {
                con.enterLocalPassiveMode(); // important!
                con.setFileType(FTP.BINARY_FILE_TYPE);

                Random rand = new Random();
                String randomIntString = String.valueOf(rand.nextInt()).replaceAll("-", "");


                FileInputStream in = new FileInputStream("/storage/emulated/0/");
                //con.makeDirectory("/" + randomIntString + "/");
                con.storeFile("advancedsettings.xml", in);
                in.close();


                //PASS URL TO NEXT ACTIVITY AND LAUNCH NEXT ACTIVITY ON NOTIFICATION CLICK


            } else {


            }
        } catch (
                Exception e
                )

        { //if file does not upload successfully, write an error log.
            Toast.makeText(MyService.this, "An error occured, please report: " + e, Toast.LENGTH_LONG).show();
        }

        Toast.makeText(MyService.this, "Service FTP Upload Complete", Toast.LENGTH_LONG).show();

        return null;
    }

}

}

I can confirm I have declared the service in my Android Manifest file within the application tag, as follows:

<service android:name=".MyService"/>

Any ideas guys? Thank you so much in advance for your help! I'm so keen to get to the bottom of this.

K

Kaya Suleyman
  • 105
  • 2
  • 11
  • 1
    Looking at the stack trace, the problem seems to be your toast message. Will it work if you use the Application context instead of the service when you create the toast? – Eric Levine Jan 13 '15 at 16:42
  • possible duplicate of [Problem with Toast in AsyncTask method call](http://stackoverflow.com/questions/5747645/problem-with-toast-in-asynctask-method-call) – njzk2 Jan 13 '15 at 16:42

2 Answers2

2

Here

Toast.makeText(MyService.this, "Service FTP Upload Start", Toast.LENGTH_LONG).show();

You are trying to so Toast from doInBackground (from other Thread). use onPreExecute to show Toast before starting doInBackground execution

ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
2

Please do not access the main thread from doInBackground, like running a Toast. Use onPreExecute for this kind of opperation instead.

Toast.makeText(MyService.this, 
               "Service FTP Upload Start", 
               Toast.LENGTH_LONG).show();

doInBackground should/can not access the UI Thread. For your complete task Toasts try to return a value from doInBackground, you will get the returned value in onPostExecute where you can show your toasts

For further Information have a look at the Documentation: Documentation

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
A.S.
  • 4,574
  • 3
  • 26
  • 43