This Guy Codes
This Guy Codes

Reputation: 125

Method must be called from main thread,currenty inferred thread is worker

I am trying to change the wallpaper of Android every 15 minutes or something like this. A user can choose the time and I am running a periodic work using Workmanager.

PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(SomeWorker.class, 15, TimeUnit.MINUTES).build();
WorkManager.getInstance().enqueue(periodicWorkRequest);

This way I am calling my Worker Class. The working class is this

public class SomeWorker extends Worker {
Context context = getApplicationContext();
private String URL;
@NonNull
@Override
public Result doWork() {
    new FetchWallpaper().execute();
    return Result.SUCCESS;
}
private class FetchWallpaper extends AsyncTask<Void, Void, Void>
{
    @Override
    protected Void doInBackground(Void... voids) {
        try
        {
            URL = "myurl.com";
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(URL)
                    .build();
            Response responses = null;
            try {
                responses = client
                        .newCall(request)
                        .execute();
                String jsonData = responses.body().string();

                JSONArray jsonArr = new JSONArray(jsonData);
                JSONObject c = jsonArr.getJSONObject(new Random().nextInt(jsonArr.length()));

                String imageUrl = c.getString("wallpaper");

                Bitmap result= Picasso.with(getApplicationContext())
                        .load(imageUrl)
                        .get();

                WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
                try {
                    wallpaperManager.setBitmap(result);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            Date currentTime = Calendar.getInstance().getTime();
        }
        catch (Exception e)
        {
            Date currentTime = Calendar.getInstance().getTime();
        }
        return null;
    }
}}

On that Particular line,

        new FetchWallpaper().execute();

I am getting the error saying it must call from the main thread. I am new to Android, I don't know if this is the good approach. Please let me know if there is any better approach to perform such kind of task.

Upvotes: 2

Views: 5347

Answers (3)

Arwy Shelke
Arwy Shelke

Reputation: 350

new AsyncTask<Void, Bitmap, Bitmap>() {
    @Override
    protected Bitmap doInBackground(Void... params) {
       Bitmap bitmap = null;
       try {
           InputStream inputStream;
           inputStream = new java.net.URL(url).openStream();
           bitmap = BitmapFactory.decodeStream(inputStream);
        }catch (Exception e) {
           logAppE(TAG, "BITMAP ERROR -> " + e.getMessage());
         }
         return bitmap
      }

      @Override
      protected void onPostExecute(Bitmap s) {
        try {
            Glide.with(context).asGif().load(s).into(imgViewGIF);
        } catch (Exception e) {
              logAppE(TAG, "BITMAP -> " + e.getMessage());
         }
      }
    }.execute();

Upvotes: 0

ianhanniballake
ianhanniballake

Reputation: 199805

The Worker class already calls doWork on a background thread - you don't need to use AsyncTask at all.

Just move everything from your doInBackground method directly into the Worker's doWork.

Upvotes: 4

Anisuzzaman Babla
Anisuzzaman Babla

Reputation: 7480

You can not update UI from doInBackground method. If you want to do something on UI you must do that on Main UI thread. So write setBitmap code in onPostExecute method as onPostExecute on on Main UI Thread.

To do that set third parameter of AsyncTask as String

AsyncTask<Void, Void, String>

So that return type of doInBackground method will be String

protected String doInBackground(Void... voids)
...
...
return imageUrl;
}

And Your onPostExecute method will be like

@Override
protected void onPostExecute(String imageUrl) {
    super.onPostExecute(imageUrl);

 Bitmap result= Picasso.with(getApplicationContext())
                    .load(imageUrl)
                    .get();

 WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
 try {
        wallpaperManager.setBitmap(result);
      } catch (Exception ex) {
        ex.printStackTrace();
      }

}

Upvotes: 0

Related Questions