Reputation: 5904
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
Upvotes: 1
Views: 697
Reputation: 43322
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();
}
}
}
}
Upvotes: 1
Reputation: 607
Use the AsyncTask, the null pointers are probably coming because you are trying to update the UI during the task's processing. You might need to use something like this from inside the AsyncTask:
activity.runOnUiThread(new Runnable() {
public void run() {
activity.doSomeSpecialUIWork();
}
});
}
Hope that works - that's what solved it for me when I was getting strange null pointers during an AsyncTask.
Here's an example from another post: how to use runOnUiThread
For your specific code, maybe this:
setWallbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
activity.runOnUiThread(new Runnable() {
public void run() {
final ProgressDialog myPd_ring=ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
// 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();
}
}
});
}
}
});
Upvotes: 0