In the android application that I am building, there are two Views, one below the other. The top one is a Login view, where I have a login form and a submit button, and there is a WebView below it.
I have implemented an AsyncTask when the login button is clicked and the request is sent to the server for login authentication. In the AsyncTask's onPreExecute() method, I create a ProgressDialog and show it. When there is a response from the server, and the login is authenticated, I dismiss the ProgressDialog in the onPostExecute() method of the AsyncTask.
The problem is that during the time the ProgressDialog is displayed, the entire screen is blackened out and does not respond to any touch. In the application that I am building, it is desired that the WebView below the Login view remains responsive to touches even when the ProgressDialog is being displayed (and the whole screen does not get blackened, only the Login view gets blackened).
Is there a way to do this? (All I need is a spinner kind of object to inform the user that some server authentication is taking place).
The following is some pieces of code from the application.
private class LoginProgressAsyncTask extends AsyncTask<Void, Void, String>{
private ProgressDialog dialog ;
protected void onPreExecute() {
dialog = ProgressDialog.show(context , null, "Verifying Login. Please wait...") ;
}
protected void onPostExecute(String result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
Then why are you using a ProgressDialog? Just add a Progress Bar to your layout and work with it the same way you're doing it with the dialog. Every dialog blackens the screen by default, it just comes from the logic of dialogs.
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.html Here is the example of progressbar usage.
Related
I have got an activity where the user can enter host name, user name and password and then click on a "Verify credentials" button. Then the credentials will be checked, which will take some time. In the meantime the user should neither be able to change the credentials nor to click on "Verify" again. So, a modal dialog like the ProgressDialog seems perfect for this.
Unfortunately, ProgressDialog has the well-know limitations regarding orientation changes etc. The guide (UI/Dialogs) tells to avoid ProgressDialog at all and use a ProgressBar in the layout instead (like in Progress & Activity). What does this mean? Shall I create another activity with just one progress bar? Or disable all input fields and put a progress bar on top of it? Sounds quite weird to me... whats your preferred solution?
Best thing which I use is:
Put a ProgressBar just beside the Login Button.
I have put a progressbar beside it(Whose visibility is set to View.GONE) in the OnCreate method.
When the user clicks on the Login/Submit button, I set the visibility of the button to View.GONE and visibility of ProgressBar to View.VISIBLE.
It looks good and the user cannot click on the button until the work is done, If an error occurs, toggle the visibility to let the user try again
Like #micro.pravi mentioned in his answer, you can implement the ProgressBar inside your layout. To keep the state after an orientation change you have to use onSaveInstanceState and onRestoreInstanceState to save and restore important values, i.e. private variables, like the private boolean isChecking
public class MyActivity extends Activity {
public boolean isProcessing;
#Override
public void onCreate(Bundle stateBundle) {
super.onCreate(stateBundle);
// Set Layout
setContentView(R.layout.main);
if(stateBundle!=null) {
// read your data here from the bundle
isProcessing = stateBundle.getBoolean("isProcessing");
}
setUiState(isChecking);
}
#Override
protected void onRestoreInstanceState(Bundle stateBundle) {
// Second value of getBoolean is the default value
isProcessing = stateBundle.getBoolean("isProcessing", false);
super.onRestoreInstanceState(stateBundle);
}
#Override
protected void onSaveInstanceState(Bundle stateBundle) {
// Save the critical data
stateBundle.putString("isProcessing", isProcessing);
super.onSaveInstanceState(stateBundle);
}
#Override
protected onResume() {
setUiState(isProcessing);
}
private setUiState(boolean processing) {
textView.setEnabled(!processing);
button.setEnabled(!processing);
progressbar.setVisibility(processing?View.VISIBLE:View.GONE);
}
}
This should be used to saved any critical data on orientation change or when the App is being killed and later restored by the OS. You don't have to save your TextView data, as the defautl View elements already handle this by themselves. Also do not store Image data this way. Instead store the Uri or path to the Url and load it on restore
For temporarily solving your problem, you can continue using the Progress Dialog and put this line in your Login Activity's tag in Manifest.xml file :
android:configChanges="orientation|keyboardHidden|screenSize"
Using this line of code will not affect the Progress Dialog on orientation changes. But it is considered a wrong practice according to Android Development's Documentation.
In the long run, i recommend you to Preserve the states for orientation changes.
I'm having trouble putting this problem into searchable terms. I'm working on an Android application, and specifically the splash screen for my app. The app needs to fetch data from an external web service (a blocking function call), while it does this the user gets a nice title, image and progress bar. When the data arrives the user is redirected to the main menu. Its a simple screen, everything being defined in the xml layout file, my problem is that I just get a black screen for a few seconds and then the main menu. If I press back I get the splash screen with the progress bar spinning away happily.
Here is what I have so far:
public class SplashActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
}
#Override
public void onStart(){
super.onStart();
DatabaseManager db = new DatabaseManager(this.getBaseContext());
db.fetchExternCatalog(); //doesnt return until data arrives
Intent intent = new Intent().setClass(this, MainMenuActivity.class);
startActivity(intent);
}
}
It seems the screen isnt actually drawn until the activity is running (after onCreate(), onStart(), etc). I thought onStart() would be the perfect place to put this, but apparently not.
So how do I draw everything on the screen and make my blocking function call after so the user actually sees the splash screen while the data is downloaded?
You're going to be locking up the UI thread which is why i believe you are seeing a black screen. Use an AsyncTask or create your own thread pool for DB operations.
As far as hitting the back button and seeing your old activity, You need to tell android not to store the activity in it's stack. This should help:
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
you need to use the ProgressDialog class to build the dialog, and then run the blocking method inside a thread.
I'll post an example in a minute (gotta get near a PC :p)
private void showSplash(){
progressDialog = ProgressDialog.show(this, "Hello! ima title", "Im the message you see.");
progressDialog.show();
Thread t = new Thread(new Runnable(){
public void run(){
// Put your blocking method here.
// You may need to build in a "hey, im done downloading" variable to get it to close down right
progressDialog.dismiss();
}
});
t.start();
}
I am developing a new app for android 2.2(Froyo), I need to know how to forcefully display a leyout before loading it with dynamic data. I have a LinearLayout with a empty List, wen the appropriate menu is selected I load it with dynamic data which takes some time to load, but wat happens is the screen is empty till the layout is filled with data. I need to display the empty layout which has ly title and show a ProgreesDialog till the list is filled with data. Here is my Activity class.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.deals);
loadDeals();//fills the list with data(URL call)
}
You can user AsyncTask for loading data. During which you will be able to show ProgressDialog as well
http://developer.android.com/reference/android/os/AsyncTask.html
Use AsynchronousTask Class and call loadDeals() from doInBackground Method.Just capture the data on that method.Then work ur UI in postExecute method.It will solve your problem
I have defined a HomeActivity with three tabs and each tab is a seperate activity.I used the example in the android developer site. http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
Tab B's (second tab) UI conatins a text and button (named Search).When the user clicks the search button,it should contact a REST webservice and show the results as a list.
In Order to do this,inside TAB B activity,on the click of the button,i call a method which creates an intent and calls a new SearchResultsActivity(referring as SRA henceforth).Inside the SRA(extends List Activity),i have the logic for connecting to the webservice and parsing the JSON result returned which displays the results as a list.I am able to achieve this functionality.But i see some drawbacks here and my questions are:
Is it fine to define a new activty (SRA) to handle the search results? or would it be better to have it handled in TAB B activity itself?The main reason why i went for a seperate activity is,the SRA extends ListActivity which would be needed if i want to display it as List and TabB is just extending Activity and wouldnt allowme to display teh results.So,is there a better way to do this?
Given the above implementation,when i navigate from TabB (click search button) to SRA,the tabs are not seen anymore.As TabB is calling a new activity(
Intent srchIntent = new Intent(TabB.this, SearchResultActivity.class);
TabB.this.startActivity(srchIntent);),the tab goes away.What could be the best solution in this case so that the tabs appear/results shown within Tab B ?
While navigating from TabB to SRA,i am trying to show a Progress dialog/Loading defined in TabB before calling StartActivity and cancel it afterwards.But the loading icon does not appear.I have tried showing the dialog and canceling in SRA as well.But the loading does not appear.
Hey Bala, what i have to say is:
1) It would be best to extend the TAB B as a ListActivity and the search done by a helper class. This way you are making your code more independent.
2) Implement 1) and you will be ok.
3) You should show a progress dialog when you start the request, and stop it when you got results. I would implement a broadcast receiver to achieve that (I can help you out, if you choose to do that).
There are two approaches to achieve this goal..
Whenever you make start your another activity (i.e. search activity), just before that set your search activity to your desired tab. You can achieve this by taking a instance of your TabActivity (i.e. your activity which is extending this class) and calling new Intent().setClass(TABACTIVITY_INSTANCE,ACTIVITY YOU_WANT_TO_SET_TO_THIS_TAB). But make to make the different objects of intent as member class .. Don't do something like this (new Intent().setClass()).
Declare the no of intent objects as no of Tabs you are holding and then use setClass method.
(This will solve your problem of the tab disappearing)
Now for taking data from server, I suggest you to implement AsyncTask (wonderful api available on Android):
private class DownloadImageTask extends AsyncTask<String, Void, String>
{
AbousUsHandler aboutHandeler;
#Override
protected void onPreExecute()
{
mProgress.setMessage("Please wait");
mProgress.show();
super.onPreExecute();
}
protected String doInBackground(String... urls)
{
/* Do you your background task i.e. getting data from server
but don't do ui related things here as this method is called in Thread
pool not on Android Ui thread.*/
return null;
}
protected void onPostExecute(String result)
{
try
{
mProgress.dismiss();
/* set Your List View Adapter here */
}
}
}
Execute this from your UI thread only by calling new DownloadImageTask().execute().
First preExecute will be called and then doInBackground and when you get your data from the server, onPostExecute will be called.
I hope this solves your problem.
I have a simple application, it starts, loads xml feed from the net, you can browse a list of news and then read details for a chosen news item. What I would like to do is have a splash screen, meaning as soon as you click application, it should display an image (app name in my case) and then display news list only after they've loaded.
I read about similar (I think) problems, and usually people say to use FrameLayout, but I can't really sort it out. I'm not sure if this can be done in the first activity that is launched, maybe I should just display this splash image in one activity and only then call activity displaying my news list?
I know that on iPhone you can set splash screen in app settings while developing, would be nice to have this functionality in android's app's manifest...
Android suggests you take advantage of using a splash screen when performing lengthy calculations on start up. Here's an excerpt from the Android Developer Website - Designing for Responsiveness:
"If your application has a time-consuming initial setup phase, consider showing a splash screen or rendering the main view as quickly as possible and filling in the information asynchronously. In either case, you should indicate somehow that progress is being made, lest the user perceive that the application is frozen." -- Android Developer Site
You can create an activity that shows a Progress Dialog while using an AsyncTask to download the xml feed from the net, parse it, store it to a db (if needed) and then start the Activity that displays the News Feeds. Close the splash Activity by calling finish()
Here's a skeleton code:
public class SplashScreen extends Activity{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// set the content view for your splash screen you defined in an xml file
setContentView(R.layout.splashscreen);
// perform other stuff you need to do
// execute your xml news feed loader
new AsyncLoadXMLFeed().execute();
}
private class AsyncLoadXMLFeed extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
// show your progress dialog
}
#Override
protected Void doInBackground(Void... voids){
// load your xml feed asynchronously
}
#Override
protected void onPostExecute(Void params){
// dismiss your dialog
// launch your News activity
Intent intent = new Intent(SplashScreen.this, News.class);
startActivity(intent);
// close this activity
finish();
}
}
}
hope that helps!
I know this is old but for those of you who are still facing this problem, you can use this simple android-splash library to show your splash screen.
SplashBuilder
.with(this, savedInstanceState)
.show();
You can set SplashTask that will execute while the splash screen is displayed.