I am trying to get data from a webserver and display a message saying "ok" or "invalid key". While it is getting the data it should produce a progress dialog. I have tried many methods including putting it inside of a thread however inside a thread the alert dialogs won't work. I have tried to use the async task method but it doesnt seem to work either. Can someone help me find a solution? Thanks
verifyCode.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
//I surround the async task with the progressdialog so that it should show while the method is working in the background
final ProgressDialog progressDialog = ProgressDialog.show(
Activate.this, "", "Loading...");
new checkActivationCode().execute(activationCode.toString().toUpperCase()
);
progressDialog.dismiss();
}
});
public class checkActivationCode extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... activationCode) {
// TODO Auto-generated method stub
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(
"https://iphone-radar.com/accounts/confirmation");
JSONObject holder = new JSONObject();
holder.put("code", activationCode);
StringEntity se = new StringEntity(holder.toString());
httpost.setEntity(se);
httpost.setHeader("Accept", "application/json");
httpost.setHeader("Content-type", "application/json");
ResponseHandler responseHandler = new BasicResponseHandler();
String response = httpclient.execute(httpost, responseHandler);
if (response != null) {
org.json.JSONObject obj = new org.json.JSONObject(response);
if ("00000000-0000-0000-0000-000000000000".equals(obj
.getString("id"))) {
new AlertDialog.Builder(Activate.this)
.setTitle(
getResources().getString(
R.string.InvalidKey))
.setMessage(
getResources()
.getString(
R.string.PleaseEntervalidRegistration))
.setNeutralButton("OK", null).show();
} else {
// add permanent variables
SharedPreferences prefs = getSharedPreferences(
"Settings", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("ACTIVATED", true);
editor.putString("ID", obj.getString("id"));
editor.commit();
Intent imTracking = new Intent(Activate.this,
ImTracking.class);
imTracking.putExtra("ActivationSuccessful", true);
// transfer more data
startActivity(imTracking);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
You can't show any kind of dialog or progress dialog from the doInBackground() method because it doesn't run on the UI Thread. You will want to update the UI with progress updates using the onProgressUpdate() method. If you want to show an AlertDialog on completion, use the onPostExecute() method. Both onProgressUpdate() and onPostExecute() run on the UI thread, so your AlertDialog code will work properly.
Here's the AsyncTask page with some sample code on how to properly use it (including where to provide updates to the UI): http://developer.android.com/reference/android/os/AsyncTask.html
Here's some SO questions covering the same topic: How to use AsyncTask to show a ProgressDialog while doing background work in Android?
Updating progress dialog in Activity from AsyncTask
How can I remove an alert dialog after a AsyncTask has done it's work
Out of curiosity...what happens if you remove the "dismiss" call immediatelty underneath your line where you show the dialogue? Any chance the dialogue is getting dismissed immediately upon creation?
Also...with other dialogues you have to go
dialogue.show()
Is a progress dialogue any different? From the docs....
Opening a progress dialog can be as simple as calling ProgressDialog.show(). For example, the progress dialog shown to the right can be easily achieved without managing the dialog through the onCreateDialog(int) callback, as shown here:
Related
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
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();
}
}
}
}
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();
}
}
});
}
}
});
I am using this code to load data from online database to my android application .
I am wondering what can i add to make this code better ?
Sometimes the progress dialog keeps spinning and never gets the data, the application is stuck then, any ideas on how i can prevent that ?
class LoadAllSections extends AsyncTask<String, String, String>
{
// make a progress dialog appear with the selected specifics
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading all sections, please wait");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
// in the background run this code to retrieve data from the server
protected String doInBackground(String... args)
{
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_Sections,"POST", params);
try
{
int success = json.getInt(TAG_SUCCESS);
sections = json.getJSONArray(TAG_SECTIONS);
if (success == 1)
{
for (int i = 0; i < sections.length(); i++)
{
JSONObject c = sections.getJSONObject(i);
section_id = c.getString(TAG_SECTION_ID);
section_name = c.getString(TAG_SECTION_NAME);
section_desc = c.getString(TAG_SECTION_DESC);
section_image = c.getString(TAG_SECTION_IMAGE);
section_valid = c.getString(TAG_SECTION_VALID);
HashMap <String,String> sectionmap = new HashMap<String,String>();
sectionmap.put(TAG_SECTION_ID, section_id);
sectionmap.put(TAG_SECTION_NAME, section_name);
sectionmap.put(TAG_SECTION_DESC, section_desc);
sectionmap.put(TAG_SECTION_IMAGE, section_image);
sectionmap.put(TAG_SECTION_VALID, section_valid);
sectionlist.add(sectionmap);
}
}
else
{
finish();
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
// disable the progress dialog and load data to the gridview
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
adapter=new SectionAdapter(MainActivity.this,sectionlist);
SectionsGridView.setAdapter(adapter);
}
}
I wanted to add a comment, but I am not allowed to.
Don't have enough reputation :-(
Pass url_section as argument to doInBackground instead of making it global.
I would place the httpRequest insde a try catch block.
Did you set the timeout, if the httpRequest is not answering? I would set that to
60 seconds. I think by default this is set to 600 seconds.
Why do you pass the file_url to onPostExecute instead of passing the
sectionList?
Take a look at AsyncTask. If you don't want to pass anything between the methods, you can also use Void. So in your case AsyncTask would also do it.
I have UI component where I have table which consist of ImageViews, Now I want to set the image from URL.
Now when I try to call asynchronously the other class where the image is set to UI it gives me error that UI can be updated only by UI thread. I want to load the UI and load images when they are available.
Here is my code :
Calling function...
new AsyncImageLoader(context,imgviewArray).execute();
// Called class..
#Override
protected Void doInBackground(Void... urls) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
int i = 0;
try{
db=new MyDB(mainact_instance);
System.out.println("Inside doInBackground");
if(isNetworkAvailable())
{
System.out.println("Network connected");
System.out.println("Fetching from network-Images");
Movie[] movies = db.selectRecords();
for(Movie mv : movies)
{
try {
URL url = new URL(IMAGE_URL+mv.getId()+".jpg");
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
images[i].setImageBitmap(bmp);
i++;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else{
System.out.println("Network not connected..fetching max id row");
}
}catch(Exception ex){ex.printStackTrace();
}
return null;
//db.close();
}
Please tell me how I can I achieve this?
move your UI thread related code to onPostExecute || onProgressUpdate
for example:
protected void onPostExecute(Long result) {
// after finishing fetching your image from URL, update the ImageView here
images[i].setImageBitmap(bmp);
}
I can see you are downloading multiple images inside the AsyncTask then you can use PublishProgress you need to update your AsyncTask definition to allow passing Bitmaps to publishProgress method as follow:
AsyncTask<whatever..., Bitmaps, whatever...>()
Then
publishProgress(yourBitmapObject);
protected void onProgressUpdate(Bitmap[] values) {
images[i].setImageBitmap(values[0]);
};
I have placed the parse method inside onCreate method. But my problem is how to show the Android Loading... Dialog??
Parse.initialize(this, "a", "b");
ParseQuery query = new ParseQuery("Category");
query.findInBackground(new FindCallback() {
#Override
public void done(List<ParseObject> catObjects, ParseException arg1) {
Log.d("Catlength", String.valueOf(catObjects.size()));
for(int i =0; i<catObjects.size(); i++){
Log.d("lengthName"+String.valueOf(i), String.valueOf(catObjects.get(i).getInt("Id")));
Category category = new Category();
category.Name= catObjects.get(i).getString("CatName");
category.id= catObjects.get(i).getInt("Id");
categories.add(category);
}
if(categories.size()>0){
setListAdapter(new CategoryArrayAdapter(CategoryListActivity.this, R.layout.row_category, categories));
}
else{
Toast.makeText(CategoryListActivity.this, "Our servers are busy. Hit refresh..", 3000).show();
}
}
});
Everything works fine in the above code but I couldn't figure out how to show the Dialog.
I'm unable to use AsycTask also as parse sdk invokes its own thread in the background and before the findInBackground execution finishes, the doInBackground completes the Asyc thread. That's why I invoked it in the main thread.
As the result I always get no results in my ArrayList.
Can someone please enlighten me.
I was in the same situation regarding the progress dialog, tried a few tricks and finally just declared a ProgressDialog class member:
protected ProgressDialog proDialog;
then created two methods:
protected void startLoading() {
proDialog = new ProgressDialog(this);
proDialog.setMessage("loading...");
proDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
proDialog.setCancelable(false);
proDialog.show();
}
protected void stopLoading() {
proDialog.dismiss();
proDialog = null;
}
and called startLoading() before the background operation and stopLoading()
inside the background operation after I got the the results.
startLoading();
ParseUser.logInInBackground(userName.getText().toString(), hashedPass, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
Log.d(Constants.TAG, "User Loged in.");
ParseManager.sCurrentUser = user;
stopLoading();
finish();
} else {
stopLoading();
invalidCreds();
}
}
});
if you want to use AsyncTask don't call findInBackground() you can use find().
you can check it out in the api https://parse.com/docs/android/api/com/parse/ParseQuery.html#find()
hope this helps.
It's easy to get the progress of both uploads and downloads using ParseFile by passing a ProgressCallback to saveInBackground and getDataInBackground. For example:
byte[] data = "Working at Parse is great!".getBytes();
ParseFile file = new ParseFile("resume.txt", data);
file.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
// Handle success or failure here ...
}
}, new ProgressCallback() {
public void done(Integer percentDone) {
// Update your progress spinner here. percentDone will be between 0 and 100.
}
});
I have two AsyncTask Activities, whose sole responsibilties are to execute an AsyncTask on the UI Thread. One of them works great, displays the progressBar, and updates the ProgressBar message. This is for my SearchActivity, which is actually a search activity with the Google Search metadata for declaring a search activity. I created a clone of the AsyncTask, and only changed doInBackground code, and also clone the SearchActivity and called it browseActivity.
I start BrowseActivity for result in a class that extends listView when an item is clicked. What I intended to happen was for the onPreExecute code of the AsyncTask to display a progressBar as the SearchActivity does, between the ListView activity, and the ResultActivity that the ListView will start onActivityResult. The onPreExcute code is being called but the ProgressBar is never displayed. (I thought I ran it on the UI thread correctly?)
Here is BrowseActivity:
AsyncTask<String, String, ArrayList<SearchResult>> browseTask;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String genreExtra = getIntent().getStringExtra(Genre.BUNDLE_TAG);
if(genreExtra!=null){
genre = Genre.getgenreFromExtra(genreExtra);
}
String categoryExtra = getIntent().getStringExtra(Category.BUNDLE_TAG);
if(categoryExtra!=null){
this.category = Category.getCategoryFromExtra(categoryExtra);
}
final Connector connector = GlobalVars.getCurrentConnector();
Thread browseThread = new Thread(){
#Override
public void run() {
try {
browseTask = connector.browse(BrowseActivity.this, category, genre, 1);
browseTask.execute("");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
runOnUiThread(browseThread);
ArrayList<SearchResult> result = null;
try {
result = browseTask.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bundle queryBundle = new Bundle();
queryBundle.putSerializable(SERIALIZABLE_KEY, result);
Intent i = new Intent();
i.putExtra(BUNDLE_KEY, queryBundle); //Put in our browse results
i.putExtra(Category.BUNDLE_TAG, category.putExtra()); //put our category in return intent
i.putExtra(Genre.BUNDLE_TAG, genre.putExtra()); //put our genre in return intent
setResult(RESULT_OK, i);
finish();
}
Here is the CategoryActivity (extends ListActivity) activity where browseActivity is started:
#Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(CategorySelectionView.this, BrowseActivity.class);
final Category[] categories = Category.values();
i.putExtra(Category.BUNDLE_TAG, categories[position].putExtra());
i.putExtra(Genre.BUNDLE_TAG, genre.putExtra());
CategorySelectionView.this.startActivityForResult(i, BrowseActivity.RESULT_REQUEST_CODE);
}
// Listen for results.
protected void onActivityResult(int requestCode, int resultCode, Intent data){
// See which child activity is calling us back.
switch (requestCode) {
case BrowseActivity.RESULT_REQUEST_CODE:
// This is the standard resultCode that is sent back if the
// activity crashed or didn't doesn't supply an explicit result.
if (resultCode == RESULT_CANCELED){
}
else {
ArrayList<SearchResult> recentQueryResults = (ArrayList<SearchResult>)data.getBundleExtra(
BrowseActivity.BUNDLE_KEY).getSerializable(BrowseActivity.SERIALIZABLE_KEY);
GlobalVars.setRecentQueryResults(recentQueryResults);
Category category = Category.getCategoryFromExtra(data.getStringExtra(Category.BUNDLE_TAG));
Intent i = new Intent(CategorySelectionView.this, RomListView.class);
i.putExtra(Category.BUNDLE_TAG, category.putExtra());
i.putExtra(Genre.BUNDLE_TAG, genre.putExtra());
startActivity(i);
}
default:
break;
}
}
Firstly, you can't run an AsyncTask on the main/UI Thread, that's the whole point. When you call browseTask.execute() its going to call its methods on the appropriate Thread (main vs background), regardless of calling runOnUiThread(). By calling runOnUiThread() all you are doing is wrapping the code that starts it in another Runnable. I think is not what you want since after calling runOnUiThread() you try to get the result of the task, which hasn't run yet. The code in onCreate() runs on the UI thread, so this has to finish before something else can run, namely the onPreExecute() of the AsyncTask.
What you should be doing is to create the AsyncTask and put everything you currently have after runOnUiThread() in onPostExecute().