travy / movie-scout

Android application which provides users a way to search through movies and view there reviews and trailers.
0 stars 0 forks source link

App Crashing #31

Closed travy closed 7 years ago

travy commented 7 years ago

The app keeps crashing after specifying an invalid api key.

Log Exception

03-27 21:34:34.844 31916-31978/com.travistorres.moviescout E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
                                                                             Process: com.travistorres.moviescout, PID: 31916
                                                                             java.lang.RuntimeException: An error occurred while executing doInBackground()
                                                                                 at android.os.AsyncTask$3.done(AsyncTask.java:325)
                                                                                 at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                                                                                 at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                                                                                 at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                                                                                 at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                                                                                 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                                 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                                 at java.lang.Thread.run(Thread.java:761)
                                                                              Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                                 at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6891)
                                                                                 at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:3225)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:760)
                                                                                 at android.view.View.setFlags(View.java:11470)
                                                                                 at android.view.View.setVisibility(View.java:8069)
                                                                                 at com.travistorres.moviescout.MainActivity.onUnauthorizedAccess(MainActivity.java:266)
                                                                                 at com.travistorres.moviescout.utils.moviedb.MovieDbRequester$NetworkingTask.doInBackground(MovieDbRequester.java:211)
                                                                                 at com.travistorres.moviescout.utils.moviedb.MovieDbRequester$NetworkingTask.doInBackground(MovieDbRequester.java:167)
                                                                                 at android.os.AsyncTask$2.call(AsyncTask.java:305)
                                                                                 at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                 at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                                                                                 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                                                                                 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                                 at java.lang.Thread.run(Thread.java:761) 
travy commented 7 years ago

This issue was being caused by modifying the visibility of error labels on the MainActivity thread while still in the SettingsActivity thread.

Essentially, while in the SettingsActivity's thread, whenever the user entered in an invalid api key the UnauthorizedNetworkException would be thrown within the Networking thread as you could see from this code snippet.

//  This is the codeblock in `MovieDbRequester.java` that performs the network request
try {
    ...
    if (json != null) {
        movieList = MovieDbParser.retrieveMovieList(json, parentActivity);
        ...
    }
}
...    
} catch (HttpUnauthorizedException e) {
    e.printStackTrace();
    errorHandler.onUnauthorizedAccess();    //  This code updates a View on MainActivity from SettingsActivity
} catch (NetworkingException e) {
...
}

After the exception is caught, the app then performs the action errorHandler.onUnauthorizedAccess() which is a method on the MainActivity which will change the visibility of a View label.

//  method from MainActivity
@Override
public void onUnauthorizedAccess() {
    mUnauthorizedTextView.setVisibility(View.VISIBLE);
}

This causes the app to crash since the View field being modified exists on the thread for MainActivity but is being modified from the thread created for the SettingsActivity.

The issue could be resolved by forcing the view element to be modified on the correct thread. The following code block should remedy the issue.

//  forces the view to be modified on the correct thread
@Override
public void onUnauthorizedAccess() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mUnauthorizedTextView.setVisibility(View.VISIBLE);
        }
    });
}

The same should be done for any other View's that are being modified within the SettingsActivity thread.

travy commented 7 years ago

The bug has been fixed.