I am trying to add a progress dialog when a new activity is launched that has to wait for a response from the internet. At the moment the screen just goes black while it is waiting. Does any one know where it needs to be placed to work?
this progressDialog:
ProgressDialog dialog = ProgressDialog.show(SearchActivity.this, "", "Loading. Please wait...", true);
dialog.dismiss();
this is in the overlayActivity extends ItemizedOverlay:
#Override
protected boolean onTap(int index) {
final OverlayItem item = (OverlayItem) items.get(index);
final Context mContext = context;
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle(item.getTitle())
.setCancelable(true)
.setPositiveButton("View Details", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(mContext, Profile.class);
intent.putExtra("id", item.getSnippet());
mContext.startActivity(intent);
}
});
AlertDialog alert = builder.create();
alert.show();
return true;
}
and this is the Profile activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.profile);
Bundle extras = getIntent().getExtras();
String id;
if (extras != null) {
id = extras.getString("id");
String xml = XMLfunctions.getXMLFromBarId(id); // makes httpPost call
Document doc = XMLfunctions.XMLfromString(xml);
NodeList nodes = doc.getElementsByTagName("result");
Element e = (Element)nodes.item(0);
// rest of profile created here
}
}
You should use Progress dialog. Progress dialog should be used in the Profile activity.
You can use the following code:
final ProgressDialog dialog = ProgressDialog.show(MyProfileActivity.this, "","Loading..Wait.." , true);
dialog.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//your code here
dialog.dismiss();
}
}, 3000); // 3000 milliseconds
Doing network calls in the UI thread (the thread which calls "onCreate") is a bad idea. It will stall the refresh of the UI till the network operation is completed. Instead, spawn a new thread in onCreate like so:
Thread networkThread = new Thread() {
public void run() {
String xml = XMLfunctions.getXMLFromBarId(id); // makes httpPost call
Document doc = XMLfunctions.XMLfromString(xml);
NodeList nodes = doc.getElementsByTagName("result");
Element e = (Element)nodes.item(0);
....
}
}
networkThread.start();
Also, I'd recommend using a ProgressDialog to show progress (which you can dismiss, once the code in the thread is done). Tutorial: http://developer.android.com/guide/topics/ui/dialogs.html
Note: You cannot dismiss the dialog from the new thread, so you will have to use a Handler to post a message from the thread to the UI thread. Here a tutorial for that: http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html
Example:
In your Profile activity class, add this:
class ProfileActivity extends Activity {
class ProfileHandler extends Handler {
private ProfileActivity parent;
public ProfileHandler(ProfileActivity parent) {
this.parent = parent;
}
public void handleMessage(Message msg) {
parent.handleMessage(msg);
}
}
private ProfileHandler handler;
public void onCreate(Bundle savedInstanceState) {
handler = new ProfileHandler(this);
Thread networkThread = new Thread() {
public void run() {
String xml = XMLfunctions.getXMLFromBarId(id); // makes httpPost call
Document doc = XMLfunctions.XMLfromString(xml);
NodeList nodes = doc.getElementsByTagName("result");
Element e = (Element)nodes.item(0);
....
ProfileActivity.this.handler.sendEmptyMessage(0);
}
}
networkThread.start();
}
public void handleMessage(msg) {
switch(msg.what) {
case 0:
// Update UI here
break;
}
}
}
Related
I'm a having a listview, of type dialog pop-up. When i click on the item of the listview, i want loading progress bar to be displayed. Below is the listview code.
public AdapterView.OnItemClickListener getOnItemClickListener() {
return new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// ProgressDialog dialog;
// dialog = ProgressDialog.show(view.getContext(), "Please wait..", "Loading data", true);
// dialog.setCancelable(false);
// dialog.show();
HashSet sometable= new HashSet();
sometable.add(i);
if (getContext() == null) return;
Intent output = new Intent();
final IData data = (IData) adapterView.getItemAtPosition(i);
//check if its myself
if((data.get("FIRST_NAME")==null)&&(data.get("LAST_NAME")==null))
output.putExtra("User","");
else{
output.putExtra("User", (String) data.get("ASSIGNEE_GUID"));
output.putExtra("userName", (String) data.get("FIRST_NAME") + " " + (String) data.get("LAST_NAME"));
//new cancelPending((Activity) getContext(),data).execute();
AssigneABO.SyncSubordinateCalendar((String) data.get("ASSIGNEE_GUID"), view.getContext());
//new MyTask(MainActivity.this).execute((Void) null);
}
Activity activity = (Activity) getContext() ;
activity.setResult(Activity.RESULT_OK,output);
activity.finish();
}
};
}
When i click on the items of the listview, starts the async task to get the data. In that async task's onprexcute method i'm calling the progress dialog as below.
public static class SyncApplicationTask extends AsyncTask<String, Context, Boolean> {
Context context;
ProgressDialog progress;// = new ProgressDialog(context);
public SyncApplicationTask(Context mcontext) {
super();
context = mcontext;
progress = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
progress.setMessage(context.getString(R.string.Sync));
progress.setTitle(R.string.sync_msg);
progress.setCanceledOnTouchOutside(false);
progress.setCancelable(false);
progress.setIndeterminate(true);
progress.show();
if (!Util.hasActiveNetworkConnection(context)) {
Util.alertMessageDialog(context, R.string.network_connection_unavailable_message);
return;
}
if (SynchronizationManager.getInstance().isSyncAllCategoryGroupActive()) {
Util.alertMessageDialog(context, R.string.synchronization_still_active);
return;
}
if (!ConnectionManager.getInstance().isServerConnected()) {
ConnectionManager.getInstance().stopServerConnection(60);
boolean isStarted = ConnectionManager.getInstance()
.startServerConnection(60); // 2 mins time out
Log.v("Connection started : ", Boolean.valueOf(isStarted)
.toString());
if (!isStarted) {
Util.alertMessageDialog(context, R.string.connection_server_lost_message);
return;
}
}
}
#Override
protected Boolean doInBackground(String... syncGroups) {
try {
SAPReXDB.synchronize(syncGroups[0]);
return true;
}catch (Exception Ex)
{ Log.v("Erron on sync: ", Ex.toString());
return false;
}
}
#Override
protected void onPostExecute(final Boolean c) {
progress.dismiss();
if(!c)
Util.alertMessageDialog(context, R.string.sync_progress_failed);
}
}
But it is displaying behind the dialog listview. I want it to display above the dialog listview. What am'i doing wrong. Can you please suggest me on this. Thank you.
With which Context do you create ProgressDialog?
GUI position & order issues can happen when you do not use normal Activity Context, but using your specific View's context or Application Context.
after this thread, i tried to make a variable status bar with this code:
private int[] loadingElementIDs;
private void initLoadingBar() {
final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp = displayMetrics.widthPixels/displayMetrics.density;
final int elementAmount = (int) (Math.floor(screenWidthInDp * 0.5f / 30) * 5);
//set margins
LinearLayout container = (LinearLayout)findViewById(R.id.loading_outer);
...
container.requestLayout();
//declare length
loadingElementIDs = new int[elementAmount];
LayoutParams LLParams = new LayoutParams(0, LayoutParams.MATCH_PARENT);
LLParams.weight = 1f;
LinearLayout element;
for (int i=0; i<elementAmount; i++) {
int id = generateViewId(); //creates unique id
element = new LinearLayout(this);
element.setVisibility(View.INVISIBLE);
element.setLayoutParams(LLParams);
element.setBackgroundDrawable(getResources().getDrawable(R.drawable.loading_inner));
element.setId(id);
element.requestLayout();
container.addView(element);
loadingElementIDs[i] = id;
}
}
this is working fine for me, but now i want to calculate sth with an asynctask and make the elements visible (code within my activity class):
private class PrefetchData extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#SuppressWarnings("static-access")
#Override
protected Void doInBackground(Void... arg0) {
try {
int step = 0;
float totalSteps = 100f;
while (...) {
step++;
// ...................
//show status
setLoadingStatus( step / totalSteps);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Intent i = new Intent(SplashScreen.this, MainActivity.class);
startActivity(i);
finish();
}
}
public void setLoadingStatus(float percentage) {
int max = (int) Math.min( Math.floor(percentage * loadingElementIDs.length),
for (int d=0; d<max; d++ ) {
((LinearLayout)findViewById(loadingElementIDs[d])).setVisibility(View.VISIBLE);
LinearLayout el = (LinearLayout)this.findViewById(loadingElementIDs[d]);
el.setVisibility(LinearLayout.VISIBLE);
}
}
And this does not work. if i call setLoadingStatus(20f); from onCreate it works perfectly, but not in the AsyncTask. Of course i do start initLoadingBar(); and new PrefetchData().execute(); in activities onCreate().
do you know what i'm doing wrong?
Use UI thread for update UI components. If you need to update task progress, you can use publishProgress(xxx) and onProgressUpdate(xxx). For more dateils: http://developer.android.com/reference/android/os/AsyncTask.html
I don't know how this got merged, the comment is all borked, but the requested code snippet is below for managing this with a Handler:
define a handler in your activity:
Handler handler = new Handler(){
handleMessage(Message msg)
{
if (msg.what == STATUS)
{
//do something if it's a message form your AsyncTask
}
else
//other messages..
}
};
when creating your AsyncTask, give it your handler. define a constructor to accept this and keep a local reference to it.
new PrefetchData(handler).execute(...);
and then inside your AsyncTask: (STATUS would be a constant setup as the message code.. )
while (...) {
step++;
// ...................
//show status
handler.obtainMessage(STATUS, step / totalSteps).sendToTarget();
}
thank you guys, i solved it with onProgressUpdate. instead of setLoadingStatus i call this:
private class PrefetchData extends AsyncTask<Void, Float, Void> {
....
protected void onProgressUpdate(Float... values) {
for (int d=0; d<Math.min( Math.floor(values[0] * loadingElementIDs.length), loadingElementIDs.length); d++ ) {
LinearLayout el = (LinearLayout)findViewById(loadingElementIDs[d]);
el.setVisibility(LinearLayout.VISIBLE);
}
}
}
You can runOnUiThread method to call Ui functions from any thread
runOnUiThread(new Runnable() {
public void run() {
// some code #3 (Write your code here to run in UI thread)
}
}); // enter code here
I have a DialogFragment which displays a simple yes/no question.
When the user presses "yes", I perform a database request (which basicaly deletes an entry).
I then toast a message to report a success or failure to the user.
I try to avoid calling the database from the UI thread, so I created a thread which will delete the entry, and from that thread I call a handler in the DialogFragment to display the toast message.
My problem is that when the user presses the button, the thread is started and the dialog is closed. As the thread is started, the data is deleted from the database. But when I toast my message from the handler, the DialogFragment is already detached from the parent Activity so I don't have a context anymore to call Toast.makeText().
My question is how can I toast the message ?
I know I could create a Service to handle the database operation, but wouldn't it be too much hassle ?
Is there a simpler way ?
Thanks !
EDIT : here is my code, to help you understand my problem :
public class EraseHistoryDialogFragment extends DialogFragment {
private HistoryDatabaseHandler mHistoryDbHandler;
private final static int MSG_NOTIFY_EMPTYDB = 1;
private final static int MSG_NOTIFY_DELENTRY = 2;
private final static int MSG_NOTIFY_NODELETION = 3;
private Context mContext;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NOTIFY_DELENTRY:
Toast.makeText(mContext,
getS tring(R.string.historytab_erased_entry),
Toast.LENGTH_SHORT).show();
break;
case MSG_NOTIFY_EMPTYDB:
Toast.makeText(mContext,
getS tring(R.string.historytab_history_cleared),
Toast.LENGTH_SHORT).show();
break;
case MSG_NOTIFY_NODELETION:
Toast.makeText(mContext,
getS tring(R.string.historytab_erase_failed),
Toast.LENGTH_SHORT).show();
break;
}
};
};
private Runnable mEraseHistoryRunnable = new Runnable() {
#Override
public void run() {
if (mHistoryDbHandler.clearAllTables()) {
mHandler.sendEmptyMessage(MSG_NOTIFY_EMPTYDB);
} else {
mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
}
}
};
private class EraseEntryRunnable implements Runnable {
private String mEntryId;
public EraseEntryRunnable(String entryID) {
mEntryId = entryID;
}
#Override
public void run() {
if (mHistoryDbHandler.deleteEntry(mEntryId)) {
mHandler.sendEmptyMessage(MSG_NOTIFY_DELENTRY);
} else {
mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
}
}
};
public static EraseHistoryDialogFragment newInstance(String message,
String entryID, boolean eraseAll) {
EraseHistoryDialogFragment frag = new EraseHistoryDialogFragment();
Bundle args = new Bundle();
args.putString("message", message);
args.putString("entryid", entryID);
args.putBoolean("eraseall", eraseAll);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mHistoryDbHandler = HistoryDatabaseHandler.getInstance(getActivity());
mContext = getActivity().getApplicationContext();
String message = getArguments().getString("message");
final String entryID = getArguments().getString("entryid");
final boolean eraseAll = getArguments().getBoolean("eraseall");
return new AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton(R.string.groupstab_yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
if (eraseAll) {
Thread emptyDbT = new Thread(
mEraseHistoryRunnable);
emptyDbT.start();
} else {
Thread deleteEntryT = new Thread(
new EraseEntryRunnable(entryID));
deleteEntryT.start();
}
}
})
.setNegativeButton(R.string.groupstab_no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
getDialog().dismiss();
}
}).create();
}
}
try with getActivity(); instead of getApplicationContext();
like this
Toast.makeText(getActivity(), "Your Message", Toast.LENGTH_SHORT).show();
Try getActivity().getApplicationContext() to get the ApplicationContext
i´m sitting fot hours now to get a progressdialog running....
i took a look at so many examples here on stackoverflow and on other sites.
The Problem:
I´m putting an progress dialog to an activity and hand it over to an async task when a button is pressed.
When the button is pressed the activity is shown about 2-3 seconds without an progressdialog, after it switched to the other activity, the progressdialog shows and terminates after async task has finished.
Coreographer tells me , that the main activity .. bla bla ..
// Get Position Button
getPosition = (Button) vg.findViewById(R.id.getPosition);
getPosition.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isAirplaneModeOn(PositionActivity.this) != true) {
try {
// System.out.println("Airplanemode off!");
if (gpsFunc.canGetLocation()) {
SharedPreferences gps = PositionActivity.this
.getSharedPreferences(prefName,
Context.MODE_PRIVATE);
String latlon = gps.getString("coordinates", null);
if (latlon != null) {
String[] split = latlon.split(";");
callWienerLinien();
latitude = Double.parseDouble(split[0]);
longitude = Double.parseDouble(split[1]);
pressed = (TextView) vg
.findViewById(R.id.pressed);
long start = new Date().getTime();
TabActivity tabs = (TabActivity) getParent();
tabs.getTabHost().setCurrentTab(1);
long end = new Date().getTime();
System.out.println(end-start);
} else {
pressed.setText("Bitte Position setzen.");
}
} else {
buildAlertMessageNoDataNetwork();
}
} catch (Exception e) {
errorOccuredMessage();
}
} else {
pressed.setText("Bitte Flugzeugmodus deaktivieren.");
}
}
});
public void callWienerLinien(){
ProgressDialog pd = new ProgressDialog(this);
pd.setMessage("Loading ...");
pt = new PublicTransport(pd,this);
pt.execute("http://webservice.qando.at/2.0/webservice.ft");
}
this is the async task
public PublicTransport(ProgressDialog pd,Context context){
this.pd = pd;
this.context = context;
getLatLonDestination();
getLatLonOrigin();
}
#Override
protected void onPreExecute(){
super.onPreExecute();
System.out.println("onpre");
pd.show();
}
#Override
protected void onPostExecute(ArrayList<PublicTransportBean> al) {
System.out.println(al.get(0).getTripDuration());
System.out.println("onpostExec");
pd.dismiss();
}
Don't show the Progressdialog within the Thread, in which you run the background task. I had the same issue and did the following:
Prepare the Dialog
Show the Dialog
Start the background task
EDIT:
Try to call the ProgressDialog as below:
runOnUiThread(new Runnable() {
#Override
public void run() {
final ProgressDialog progressDialog=new ProgressDialog(cont);
progressDialog.setMessage("Progress");
progressDialog.show();
}
});
I solved the problem ....
i´m calling the
TabActivity tabs = (TabActivity) getParent();
tabs.getTabHost().setCurrentTab(1);
in the postexecute of the async task.
Working perfect ..... two lines of code and 13 hours of studying :-(
I am having a progress dialog for a process. But i am taking a null pointer exception in my thread. But, when i remove the progress dialog. I am no longer taking an exception.
My code is as this
public class PlayedActivity extends ListActivity {
private PullToRefreshListView listView;
final Context context = this;
public Handler handler;
Runnable sendNumbers2;
List<On> playedOn;
DatabaseHandlerOn db;
private ProgressDialog m_ProgressDialog;
private ArrayList<On> m_results = null;
private PlayedOnAdapter m_adapter;
#SuppressLint({ "HandlerLeak", "HandlerLeak" })
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playedonnumara);
db = new DatabaseHandlerOnNumara(getApplicationContext());
m_results = new ArrayList<OnNumara>();
this.m_adapter = new PlayedOnNumaraAdapter(this, R.layout.playedrowon, m_results);
this.setListAdapter(this.m_adapter);
sendNumbers2 = new Runnable() {
#Override
public void run() {
playedOn = db.getAllContacts();
for (On on : playedOn) {
m_results.add(on);
}
Collections.reverse(m_results);
//m_ProgressDialog.dismiss();
handler.sendEmptyMessage(0);
}
};
Thread thread = new Thread(sendNumbers2,"sendNumbers2");
thread.start();
/*m_ProgressDialog = ProgressDialog.show(PlayedOnNumaraActivity.this,
"",getString(R.string.PleaseWait), true);
m_ProgressDialog.setCancelable(true);
*/
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
m_adapter.notifyDataSetChanged();
}
};
}
}
}
The code above is working and takes no exception when progress dialog codes are commented
Without your LogCat logs, I can only guess.
m_ProgressDialog is defined after you start your thread. Why? Define it before the thread is started.
Also, I would recommend an AsyncTask for this, instead. See Painless Threading for details on that.