0

I have a code that reads my inbox and stores each read SMS as a separate file in a fixed folder which i need to upload on FTP later on. I am using the intent for FTP Upload. My program stucture is something like: onCreate() -> Method1 inbox read -> Delete inbox messages -> Method2 Upload FTP -> Method3 Delete Uploaded Folder -> Further Tasks The problem is that Further Tasks are called before the app is done uploading the folder contents and the server is simply disconnected. I tried calling Method3 in the Further Tasks with the help of a Handler set at delay of 10 minutes but it didn't help as upload may take a lot more time than that also it may not have any files at all to upload so those 10 minutes are wasted. I want the app to wait till the upload is complete. So the question is: What is the proper way of doing this?
EDIT :
The code i am using:

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ReadnDeleteSMS();
    }
    public void FTPUpload(){     //FTPUpload via ANDFTP app
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_PICK);
            Uri ftpUri = Uri.parse("Server");       //Server Call
            intent.setDataAndType(ftpUri, "vnd.android.cursor.dir/lysesoft.andftp.uri");
            intent.putExtra("command_type", "upload");
            intent.putExtra("ftp_username", "username");
            intent.putExtra("ftp_password", "password");
            intent.putExtra("ftp_pasv", "true");        
            intent.putExtra("ftp_resume", "true");
            intent.putExtra("ftp_encoding", "UTF-8");
            intent.putExtra("progress_title", "Uploading folder ...");
            intent.putExtra("local_file1", "/sdcard/ReceivedSMS");
            intent.putExtra("remote_folder", "remote folder");
            intent.putExtra("close_ui", "true");        //Finally start the Activity
            startActivityForResult(intent, RESULT_OK); i++;
            customHandler.postDelayed(finalizer, 10*60*1000);}

        public void ReadnDeleteSMS(){       //Reads, BackUps and Deletes Inbox Messages
            Cursor cursor1 = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
            if (cursor1.getCount() > 0) {
                while (cursor1.moveToNext()){
                    int id = cursor1.getInt(0);
                    String address = cursor1.getString(cursor1.getColumnIndex("address"));
                    String date = cursor1.getString(cursor1.getColumnIndex("date"));
                    String SMSDate = DateConversion(date);
                    String msg = cursor1.getString(cursor1.getColumnIndex("body"));
                    ReadSMS = address + "\n" + SMSDate + "\n" + msg + "\n";
                    FileName(zText);
                    myDate = zText.toString(); zText = new StringBuilder();
                    fileWrite("/sdcard/ReceivedSMS/" + myDate, ReadSMS);
                    try{
                     getApplicationContext().getContentResolver().delete(Uri.parse("content://sms/" + id), null, null);
                     Toast.makeText(getBaseContext(), "Successfully Deleted", Toast.LENGTH_SHORT).show();}
                    catch(Exception e){
                        Toast.makeText(getBaseContext(), "Error Deleting", Toast.LENGTH_SHORT).show();}}}
            FTPUpload();}
  public String DateConversion (String date){           //Proper Date Format Display
        Long timestamp = Long.parseLong(date);    
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        return calendar.getTime().toString();}

    public void FileName(StringBuilder zText) {         //Inbox Message File Name
        SimpleDateFormat mSDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        myDate = mSDF.format(new Date());
        myDate = myDate.replace(" ", "");
        myDate = myDate.replace("/", "");
        myDate = myDate.replace(":", "");
        myDate = myDate.replace(".", "");
        zText.append(myDate);}
    public Runnable finalizer = new Runnable(){     //Main Handler
            public void run(){
                if (i > 0)
                {DeleteDirectory("/sdcard/ReceivedSMS"); i = 0;}
    //Some Further Tasks
    }

These further tasks are to be called often but if the upload is under execution, no such tasks must perform. The tasks include reading a webpage, String editing and such. These are the main tasks of my app.

1 Answers1

0

Without posting some of the code you are using to do this process is difficult to help you but if your problem is that you have to wait until one task finishes to start another then that seems a job for sendBroadcast and BroadcastReceiver.

Example

Say you handle the logic of the ftp upload in a Service (for simplicity, this logic could be on an AsyncTask or anything similar):

public class RefreshService extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            // Backgroud process here
            // ...
            // When the task is completed
            sendBroadcast(new Intent("com.example.action.REFRESH_COMPLETED"));
        }
    }
}

In order to catch that com.example.action.REFRESH_COMPLETED you have to provide a BroadcastReceiver.

public class RefreshCompletedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // The logic you want to execute right after the background task is completed
    }

}

You also have to state that this class should catch the specific action you defined before. To do this, update your manifest and include the receiver:

...
        <service
            android:name=".RefreshService"
            android:exported="false" >
        </service>

        <receiver android:name=".RefreshCompletedReceiver" >
            <intent-filter>
                 <action android:name="com.example.action.REFRESH_COMPLETED" />
            </intent-filter>
        </receiver>
...

And that's it. The code in the BroadcastReceiver will execute after the background process finishes. Keep in mind that you'll need to handle an interruption of the process or similar network errors and only call sendBroadcast when the operation was successful.

Additional Info

  • You can dynamically register the receiver using registerReceiver in the context but you'll have to unregister it (typically on the onDestroy method of your activity) or your app will crash (see the reference).
  • This helped me a lot with this sort of problems.
  • Also check this question to choose between Service and AsyncTask.
  • Check the docs here and here for more info on both.

Disclaimer

I just started programming in android so there might be another way to do this, I just found this way easy to understand and easier to implement.

Community
  • 1
  • 1
jhoanegar
  • 318
  • 4
  • 6
  • i have edited the question to add my code. I don't see a way to add your receiver in current code. I dunno. I am new with android myself. Thanks for all the help :) – Owais Cheema Jul 21 '14 at 10:14
  • It seems to me that `FTPUpload` will be a recurrent task so what you want is an `IntentService` just like the want in the example that waits in the background for requests and in its method `onHandleIntent` you'll do what you're doing in `FTPUpload` WITHOUT the `postDelayed`. In the last line of `onHandle intent` you use `sendBroadcast` to notify that the task was completed and in your `Receiver` class you execute the logic in `ReadnDeleteSMS`. That way your UI Activity won't block and you only execute the clean up method when the process was successful. Check the links I provided. – jhoanegar Jul 21 '14 at 20:47