0

I have a problem with AsyncTask in my app. AsyncTask is located in SplashScreenAcivity.java. It downloads data using json for MainActivity.java while showing splash screen. When data is loaded, app shows MainActivity screen. However, when i turn off internet connection app crashes. Instead of it i would like to move to MainActivity.java and show toast that internet connection must be turned on. SplashScreen.java loads data for listView in MainActivity.

SplashActivityScreen.java

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash_screen);

    new DownloadData().execute();

}

private class DownloadData extends AsyncTask<Void, Void, Void> {



    @Override
    protected Void doInBackground(Void... voids) {

                SyncHttpClient clientOne = new SyncHttpClient();
                clientOne.get("https://api.themoviedb.org/3/tv/top_rated?api_key=d253f520df9cd868af7db8daaa0db8fb&language=en-US", new JsonHttpResponseHandler() {

                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {

                        try {

                            tvseries0 = response.getJSONArray("results").getJSONObject(0).getString("name");
                            tvseries1 = response.getJSONArray("results").getJSONObject(1).getString("name");
                            tvseries2 = response.getJSONArray("results").getJSONObject(2).getString("name");
                            tvseries3 = response.getJSONArray("results").getJSONObject(3).getString("name");
                            tvseries4 = response.getJSONArray("results").getJSONObject(4).getString("name");
                            tvseries5 = response.getJSONArray("results").getJSONObject(5).getString("name");
                            tvseries6 = response.getJSONArray("results").getJSONObject(6).getString("name");
                            tvseries7 = response.getJSONArray("results").getJSONObject(7).getString("name");
                            tvseries8 = response.getJSONArray("results").getJSONObject(8).getString("name");
                            tvseries9 = response.getJSONArray("results").getJSONObject(9).getString("name");
                            tvseries10 = response.getJSONArray("results").getJSONObject(10).getString("name");
                            tvseries11 = response.getJSONArray("results").getJSONObject(11).getString("name");
                            tvseries12 = response.getJSONArray("results").getJSONObject(12).getString("name");
                            tvseries13 = response.getJSONArray("results").getJSONObject(13).getString("name");
                            tvseries14 = response.getJSONArray("results").getJSONObject(14).getString("name");
                            tvseries15 = response.getJSONArray("results").getJSONObject(15).getString("name");
                            tvseries16 = response.getJSONArray("results").getJSONObject(16).getString("name");
                            tvseries17 = response.getJSONArray("results").getJSONObject(17).getString("name");
                            tvseries18 = response.getJSONArray("results").getJSONObject(18).getString("name");
                            tvseries19 = response.getJSONArray("results").getJSONObject(19).getString("name");

                        } catch (JSONException e) {

                            e.printStackTrace();

                        }

                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers,Throwable e , JSONObject response) {

                        Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();

                    }
                });

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        Intent i = new Intent(getApplicationContext(), MainActivity.class);

        i.putExtra("tvseries0", tvseries0);
        i.putExtra("tvseries1", tvseries1);
        i.putExtra("tvseries2", tvseries2);
        i.putExtra("tvseries3", tvseries3);
        i.putExtra("tvseries4", tvseries4);
        i.putExtra("tvseries5", tvseries5);
        i.putExtra("tvseries6", tvseries6);
        i.putExtra("tvseries7", tvseries7);
        i.putExtra("tvseries8", tvseries8);
        i.putExtra("tvseries9", tvseries9);
        i.putExtra("tvseries10", tvseries10);
        i.putExtra("tvseries11", tvseries11);
        i.putExtra("tvseries12", tvseries12);
        i.putExtra("tvseries13", tvseries13);
        i.putExtra("tvseries14", tvseries14);
        i.putExtra("tvseries15", tvseries15);
        i.putExtra("tvseries16", tvseries16);
        i.putExtra("tvseries17", tvseries17);
        i.putExtra("tvseries18", tvseries18);
        i.putExtra("tvseries19", tvseries19);

        startActivity(i);

        finish();

    }
}

}

Crash 1

04-30 13:15:35.165 12349-12365/przemo.me.recommend.recommendme E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: przemo.me.recommend.recommendme, PID: 12349
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:318)
    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: java.lang.RuntimeException: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at com.loopj.android.http.AsyncHttpResponseHandler.onUserException(AsyncHttpResponseHandler.java:304)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:395)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319)
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109)
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56)
    at android.os.AsyncTask$2.call(AsyncTask.java:304)
    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) 
 Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:200)
    at android.os.Handler.<init>(Handler.java:114)
    at android.widget.Toast$TN.<init>(Toast.java:346)
    at android.widget.Toast.<init>(Toast.java:101)
    at android.widget.Toast.makeText(Toast.java:260)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData$1.onFailure(SplashScreenActivity.java:103)
    at com.loopj.android.http.JsonHttpResponseHandler.onFailure(JsonHttpResponseHandler.java:233)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:359)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401) 
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319) 
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109) 
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95) 
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078) 
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037) 
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64) 
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56) 
    at android.os.AsyncTask$2.call(AsyncTask.java:304) 
    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) 

Crash 2

04-30 13:15:35.162 12349-12365/przemo.me.recommend.recommendme E/AsyncHttpRH: User-space exception detected!
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:200)
    at android.os.Handler.<init>(Handler.java:114)
    at android.widget.Toast$TN.<init>(Toast.java:346)
    at android.widget.Toast.<init>(Toast.java:101)
    at android.widget.Toast.makeText(Toast.java:260)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData$1.onFailure(SplashScreenActivity.java:103)
    at com.loopj.android.http.JsonHttpResponseHandler.onFailure(JsonHttpResponseHandler.java:233)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:359)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319)
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109)
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56)
    at android.os.AsyncTask$2.call(AsyncTask.java:304)
    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)
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
Przemo
  • 111
  • 9
  • Possible duplicate of [Can't create handler inside thread that has not called Looper.prepare()](https://stackoverflow.com/questions/3875184/cant-create-handler-inside-thread-that-has-not-called-looper-prepare) – ADM Apr 30 '18 at 13:26
  • You can use BroadcastReceiver for network fluctuations and handle your action accordingly...e.g. if your asynctask is running and in between your network goes off then your BroadcastReceiver will get callback and there you can perform your action – Nikhil Lotke Apr 30 '18 at 13:27

4 Answers4

3

You can not do UI operations from non UI thread. Like in your code you are showing Toast in Async task thread.

You should replace

Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     

with this

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     
        }
    });
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
  • It shows the message but when i place there intent to move to MainActivity.java it still crashes – Przemo Apr 30 '18 at 14:23
  • I have seen your code. There can be many improvements in your code. like why you need asyncTask. Does SyncHttpClient not take responsibility to download data in background thread? – Khemraj Sharma Apr 30 '18 at 14:36
  • You are right. I removed AsyncTask. However, still app crashes when i want to move to MainActivity.java which contains listview. I am getting an error: "Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference" – Przemo Apr 30 '18 at 14:52
  • Clearly some of your object is null and you are trying to use it further. Post your stack trace, you will get an line number and the object which is null. – Khemraj Sharma Apr 30 '18 at 14:56
1

use -

SplashScreenActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     
        }
    });
Sanjay Kumar
  • 1,135
  • 14
  • 27
1

Here is a server connection AsyncTask task that I created years ago in Android Java. The background task works successfully. I used it to update in the background the data repository in the App I developed at that time.

public class DataExchangeStore extends Application {
    public void startServerConnection(Context contextGlobal, Activity activityGlobal) {
        this.contextGlobal = contextGlobal;
        this.activityGlobal = activityGlobal;
        connectTask = new ConnectTask();
        connectTask.execute("");
    }

    private ConnectTask connectTask;

    public class ConnectTask extends AsyncTask<String, String, TCPClient> {
        @Override
        protected TCPClient doInBackground(String... message) {
            android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_BACKGROUND);
            // we create a TCPClient object
            mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
                @Override
                // here the messageReceived method is implemented
                public void messageReceived(ChatMessage message) {
                    // this method calls the onProgressUpdate
                    publishProgress(message.getMessage());
                }
            }, contextGlobal, activityGlobal);
            mTcpClient.run();
            return null;
        }
        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            System.err.println(values[0]);
            // do your stuff here
        }
    }

Import is to permanently lock the screen orientation of the activity, specifying the screenOrientation attribute in the Android-Manifest file with portrait or landscape values:

<activity android:screenOrientation="portrait" />
Flying Dutchman
  • 135
  • 1
  • 6
0

Although previous answers are not wrong, using runOnUiThread() to jump out of the background thread in the AsyncTask is not a good practice. You have the onPostExecute() method for that.

What you should be doing is passing a result object to onPostExecute(). This object would encapsulate the result state (ie: error or success) and the actual data received. Then in onPostExecute() you check the result state and display a Toast if the state is error.

And do yourself a favor and replace your 20 TvSerie objects by a List<TvSerie> and do a loop in you AsyncTask to populate the list.

Please refer to the AsyncTask documentation for details on how to properly use it.

JDenais
  • 2,956
  • 2
  • 21
  • 30