Search code examples
javaandroidmultithreadingrunnableandroid-wallpaper

Calculate time thread android


I'm using a thread to set an image as background and in this thread i have a dialog. The dialog starts and should be close when the wallpaper will be set. This is the code so far

setWallbtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                final ProgressDialog myPd_ring=ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
                new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                           // TODO Auto-generated method stub
                            WallpaperManager wallManager = WallpaperManager.getInstance(getApplicationContext());
                            try {
                                image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
                                wallManager.setBitmap(image);
                                Toast.makeText(SingleWall.this, "Wallpaper Set Successfully!!", Toast.LENGTH_SHORT).show();
                                myPd_ring.dismiss();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                                Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_SHORT).show();
                                myPd_ring.dismiss();
                            }
                        }
                    }, 4000);


            }
        });

So, on click in a button starts the thread and for 4 seconds the dialog should be visible with the progress icon. But it is not correct! the time to set the background could be more or less than 4 seconds! So the 4000 should be calculates in base of the time to set the image as wallpaper. Is it possible?

ps. I can't use a AsyncTask because i get many NullPointerExceptions


Solution

  • Note that you are not using a separate Thread with the code in your question, you are running a Runnable on the main UI thread.

    If you look at the documentation, it's recommended to use an AsyncTask for decoding Bitmaps, and it's also the best way to achieve your desired result, where the ProgressDialog is dismissed only after the process is complete, which can take an unpredictable amount of time.

    You just need to put the code in it's correct place, and give it what it needs through the varargs passed in.

    Here is how you should start the AsyncTask:

        setWallbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               new LoadImage().execute(url);
            }
        });
    

    Then, create the AsyncTask as a sub-class of the SingleWall Activity. Put the network code in doInBackground() which will download and decode the Bitmap, and then put the UI related code in onPostExecute(), which runs on the UI thread.

    Note that you can also use a WeakReference to the WallpaperManager instance, as outlined in the link above, but I'll keep it simple here and just access wallManager directly, which you can do if the AsyncTask is a sub-class of your Activity.

    class LoadImage extends AsyncTask<URL, Void, Bitmap> {
    
        ProgressDialog myPd_ring;
    
        @Override
        protected void onPreExecute() {
            //Start Progress Dialog here
            myPd_ring = ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
        }
    
        //Runs in a background Thread
        @Override
        protected Bitmap doInBackground(URL... params) {
            URL url = params[0];
            Bitmap image = null;
            try {
                image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return image;
        }
    
        //Runs on the UI Thread
        @Override
        protected void onPostExecute(Bitmap image) {
            myPd_ring.dismiss();
    
            if (image == null){
                Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_LONG).show();
            }
            else{
                //set image here
                try {
                    SingleWall.this.wallManager.setBitmap(image);
    
                    Toast.makeText(SingleWall.this, "Wallpaper Set Successfully!!", Toast.LENGTH_SHORT).show();
    
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_LONG).show();
                }
    
            }
        }
    }