Search code examples
javaandroidioexceptiongoogle-tasks-apigoogle-tasks

How to handle IOException?


I am trying to sync google task in my application. I have created a class to handle the methods used to get list of task and all task related methods.

These methods I want to call in UI.

For testing purpose I have created a class which extends AsyncTask in this I have called the method to getTaskList. But It is throwing an exception and I think I have handled it in a wrong way.

I want to know for the method of getTaskList the parameter provided is listId. It should return all the task from the list of specified id.

Now how should I pass the Id of list to test if it dose return all the tasks or not?

For now I am getting error as:

    FATAL EXCEPTION: AsyncTask #1
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime: Process: com.example.siddhi.taskdemo, PID: 15993
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.AsyncTask$3.done(AsyncTask.java:304)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.lang.Thread.run(Thread.java:818)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:  Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.Handler.<init>(Handler.java:200)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.Handler.<init>(Handler.java:114)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.widget.Toast$TN.<init>(Toast.java:344)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.widget.Toast.<init>(Toast.java:100)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.widget.Toast.makeText(Toast.java:258)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at com.example.siddhi.taskdemo.TestAsyncTask.doInBackground(TestAsyncTask.java:54)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at com.example.siddhi.taskdemo.TestAsyncTask.doInBackground(TestAsyncTask.java:25)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
03-30 21:21:10.593 15993-16025/com.example.siddhi.taskdemo E/AndroidRuntime:     at java.lang.Thread.run(Thread.java:818) 

Main activity:

  public class MainActivity extends AppCompatActivity {
        GoogleAccountCredential mCredential;
        public TextView mOutputText;
        ProgressDialog mProgress;

        static final int REQUEST_ACCOUNT_PICKER = 1000;
        static final int REQUEST_AUTHORIZATION = 1001;
        static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
        private static final String PREF_ACCOUNT_NAME = "accountName";
        private static final String[] SCOPES = { TasksScopes.TASKS };
        public com.google.api.services.tasks.Tasks mService = null;
        /**
         * Create the main activity.
         * @param savedInstanceState previously saved instance data.
         */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            LinearLayout activityLayout = new LinearLayout(this);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            activityLayout.setLayoutParams(lp);
            activityLayout.setOrientation(LinearLayout.VERTICAL);
            activityLayout.setPadding(16, 16, 16, 16);

            ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);

            mOutputText = new TextView(this);
            mOutputText.setLayoutParams(tlp);
            mOutputText.setPadding(16, 16, 16, 16);
            mOutputText.setVerticalScrollBarEnabled(true);
            mOutputText.setMovementMethod(new ScrollingMovementMethod());
            activityLayout.addView(mOutputText);

            mProgress = new ProgressDialog(this);
            mProgress.setMessage("Calling Google Tasks API ...");

            setContentView(activityLayout);

            // Initialize credentials and service object.
            SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
            mCredential = GoogleAccountCredential.usingOAuth2(
                    getApplicationContext(), Arrays.asList(SCOPES))
                    .setBackOff(new ExponentialBackOff())
                    .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));

            HttpTransport transport = AndroidHttp.newCompatibleTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
            mService = new com.google.api.services.tasks.Tasks.Builder(
                    transport, jsonFactory, mCredential)
                    .setApplicationName("Google Tasks API Android Quickstart")
                    .build();
        }


        /**
         * Called whenever this activity is pushed to the foreground, such as after
         * a call to onCreate().
         */
        @Override
        protected void onResume() {
            super.onResume();
            if (isGooglePlayServicesAvailable()) {
                refreshResults();
            } else {
                mOutputText.setText("Google Play Services required: " +
                        "after installing, close and relaunch this app.");
            }
        }

        /**
         * Called when an activity launched here (specifically, AccountPicker
         * and authorization) exits, giving you the requestCode you started it with,
         * the resultCode it returned, and any additional data from it.
         * @param requestCode code indicating which activity result is incoming.
         * @param resultCode code indicating the result of the incoming
         *     activity result.
         * @param data Intent (containing result data) returned by incoming
         *     activity result.
         */
        @Override
        protected void onActivityResult(
                int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            switch(requestCode) {
                case REQUEST_GOOGLE_PLAY_SERVICES:
                    if (resultCode != RESULT_OK) {
                        isGooglePlayServicesAvailable();
                    }
                    break;
                case REQUEST_ACCOUNT_PICKER:
                    if (resultCode == RESULT_OK && data != null &&
                            data.getExtras() != null) {
                        String accountName =
                                data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                        if (accountName != null) {
                            mCredential.setSelectedAccountName(accountName);
                            SharedPreferences settings =
                                    getPreferences(Context.MODE_PRIVATE);
                            SharedPreferences.Editor editor = settings.edit();
                            editor.putString(PREF_ACCOUNT_NAME, accountName);
                            editor.apply();
                        }
                    } else if (resultCode == RESULT_CANCELED) {
                        mOutputText.setText("Account unspecified.");
                    }
                    break;
                case REQUEST_AUTHORIZATION:
                    if (resultCode != RESULT_OK) {
                        chooseAccount();
                    }
                    break;
            }

            super.onActivityResult(requestCode, resultCode, data);
        }

        /**
         * Attempt to get a set of data from the Google Tasks API to display. If the
         * email address isn't known yet, then call chooseAccount() method so the
         * user can pick an account.
         */
        private void refreshResults() {
            if (mCredential.getSelectedAccountName() == null) {
                chooseAccount();
            } else {
                if (isDeviceOnline()) {
                    new TestAsyncTask(mCredential, MainActivity.this).execute();
                } else {
                    mOutputText.setText("No network connection available.");
                }
            }
        }
        /**
         * Starts an activity in Google Play Services so the user can pick an
         * account.
         */
        private void chooseAccount() {
            startActivityForResult(
                    mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
        }

        /**
         * Checks whether the device currently has a network connection.
         * @return true if the device has a network connection, false otherwise.
         */
        private boolean isDeviceOnline() {
            ConnectivityManager connMgr =
                    (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
            return (networkInfo != null && networkInfo.isConnected());
        }

        /**
         * Check that Google Play services APK is installed and up to date. Will
         * launch an error dialog for the user to update Google Play Services if
         * possible.
         * @return true if Google Play Services is available and up to
         *     date on this device; false otherwise.
         */
        private boolean isGooglePlayServicesAvailable() {
            final int connectionStatusCode =
                    GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
            if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
                showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
                return false;
            } else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
                return false;
            }
            return true;
        }

        /**
         * Display an error dialog showing that Google Play Services is missing
         * or out of date.
         * @param connectionStatusCode code describing the presence (or lack of)
         *     Google Play Services on this device.
         */
        void showGooglePlayServicesAvailabilityErrorDialog(
                final int connectionStatusCode) {
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
                    connectionStatusCode,
                    MainActivity.this,
                    REQUEST_GOOGLE_PLAY_SERVICES);
            dialog.show();
        }

    }

TestAsyncTask

  public class TestAsyncTask extends AsyncTask<Void, Void, List<Task>>{

    private com.google.api.services.tasks.Tasks mService = null;
    private Exception mLastError = null;
    private MainActivity activity;
    private com.google.api.services.tasks.Tasks client = null;

    public TestAsyncTask(GoogleAccountCredential credential, MainActivity activity) {
        HttpTransport transport = AndroidHttp.newCompatibleTransport();
        JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        mService = new com.google.api.services.tasks.Tasks.Builder(
                transport, jsonFactory, credential)
                .setApplicationName("Google Tasks API Android Quickstart")
                .build();
        this.activity = activity;
    }

    protected List<Task> doInBackground(Void... params) {

        GTaskSyncer gTaskSyncer = new GTaskSyncer(activity);

        List<Task> result = new ArrayList<>();

        try {

            result = gTaskSyncer.getTaskList("Bdjxxuj");

        } catch (IOException e) {

            Toast.makeText(activity,"IO Exception",Toast.LENGTH_SHORT).show();
        }
        return result;
    }


    @Override
    protected void onPostExecute(List<Task> output) {
        activity.mProgress.hide();
        if (output == null || output.size() == 0) {
            activity.mOutputText.setText("No results returned.");
        } else {
            activity.mOutputText.setText(TextUtils.join("\n", output));
        }
    }
}

GTaskSyncer

 public class GTaskSyncer
{

    final MainActivity activity;
    final com.google.api.services.tasks.Tasks mService;
    private Exception mLastError = null;



    GTaskSyncer(MainActivity activity) {
        this.activity = activity;
        mService = activity.mService;
    }

    public List<TaskList> getAllTaskList() throws IOException
    {
        List<TaskList> result = new ArrayList<TaskList>();

        TaskLists taskLists = mService.tasklists().list().execute();

        for (TaskList taskList : taskLists.getItems()) {

                result.add(taskList);
        }

        return result;

    }


    public TaskList createList() throws IOException
    {

        TaskList taskList = new TaskList();

        taskList =  activity.mService.tasklists().insert(taskList).execute();

        return taskList;
    }

    public Task createTask(String listId) throws IOException
    {

        Task task = new Task();

        task =   activity.mService.tasks().insert(listId, task).execute();

        return  task;
    }

    public Task getTask(String listId,String taskId) throws IOException
    {

        Task task =   activity.mService.tasks().get(listId, taskId).execute();

        return task;
    }

    public List<Task> getTaskList(String listId) throws IOException {


        List<Task> result = new ArrayList<Task>();

        List<Task> tasks = mService.tasks().list(listId).execute().getItems();

        if (tasks != null) {

            for (Task task : tasks) {

                result.add(task);
            }
        } else {

            Toast.makeText(activity, "No tasks.", Toast.LENGTH_SHORT).show();
        }

        return result;
    }

}

Please help..


Solution

  • You can't show a toast in the background thread.

    use this:

       Handler handler = new Handler(Looper.getMainLooper());
       handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(activity, "No tasks.", Toast.LENGTH_SHORT).show();
            }
        });