Flag from AsyncTask class doesn't work properly in main class - java

I've created some lines of code which are supposed to switch to the next activity if connection is set without any exceptions. But if there are some exceptions, it should make "Error!" toast and not go to the next activity.
Boolean flag in Connection class works well: if the server is off, app will say "Error!", if on, it won't. But same flag in main class (con.flag) doesn't work properly, it looks like it is always false. App always switches to the next activity, with making toast or without, depending on server status. What's wrong in my code? I suppose that there's something I don't know about AsyncTask classes' fields initialization.
So, here is my code:
public class Connection extends AsyncTask<Void, Void, String> {
Context mContext;
public Connection(Context context){
this.mContext = context;
}
static String value;
boolean flag = false;
#Override
protected String doInBackground(Void... arg0) {
try {
Jedis jedis = new Jedis("192.168.0.120", 6381);
String name = jedis.ping();
value = name;
} catch (Exception e){
flag = true;
}
return null;
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (flag) {
Toast toast = Toast.makeText(mContext,
"Error!", Toast.LENGTH_LONG);
toast.show();
}
}
}
public class MainActivity extends AppCompatActivity {
Button click;
Context maincontext = this;
public void goTo2ndActivity(){
Intent intent = new Intent(this, Main2Activity.class);
startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
click = (Button)findViewById(R.id.button);
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Connection con = new Connection(maincontext);
con.execute();
if (!con.flag){
goTo2ndActivity();
}
}
});
}
}

Your problem seems to be a race condition between main thread and the asynctask, the problem is in the onClick listener:
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Connection con = new Connection(maincontext);
con.execute();
if (!con.flag){
goTo2ndActivity();
}
}
});
so this part
if (!con.flag){
goTo2ndActivity();
}
must be called from on post execute of your async task, for that pass the activity to the constructor of the async task like this:
update constructor of async task:
public class Connection extends AsyncTask<Void, Void, String> {
Context mContext;
MainActivity activity;
public Connection(Context context,MainActivity activity){
this.mContext = context;
this.activity= activity
}
..........
..........
and on post execute:
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (flag) {
Toast toast = Toast.makeText(mContext,
"Error!", Toast.LENGTH_LONG);
toast.show();
}else{
//go to next activity
activity.goTo2ndActivity();
}
}
now your button click becomes:
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//just execute
final Connection con = new Connection(maincontext,this);
con.execute();
}
});

Related

Android Splash Screen AsyncTask

Basically I have a loading splash screen which will be executed when button was clicked:
public void onClick(View v) {
// Load the loading splash screen
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
});
And in the LoadingScreen class:
public class LoadingScreen extends Activity{
//A ProgressDialog object
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Initialize a LoadViewTask object and call the execute() method
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in separate thread
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(LoadingScreen.this,"Getting routes...",
"Loading data, please wait...", false, false);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(750);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
//set the current progress of the progress dialog
progressDialog.setProgress(values[0]);
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
}
}
}
With these codes, the loading splash screen did came out. But I wonder is there any other way to show only the pop out dialogue for loading progress bar which on top on my previous screen?
Let's say my previous screen was event details. Then when user selected the button, only the dialogue box with loading progress bar will be shown instead of a new intent with a dialogue box.
Any ideas? Thanks in advance.
EDIT
public void onClick(View v) {
// Load the loading splash screen
new LoadViewTask().execute();
ENeighbourhoodActivity.tvDirection.setText("");
eventModel.setEventX(String.valueOf(eventModel.getEventX()));
eventModel.setEventY(String.valueOf(eventModel.getEventY()));
new GetEventDirectionAsyncTask(new GetEventDirectionAsyncTask.OnRoutineFinished() {
public void onFinish() {
//Hide the callout and plot user location marker
ENeighbourhoodActivity.callout.hide();
EventController.getUserLocation(context);
getActivity().finish();
}
}).execute(eventModel);
}
});
public class GetRegisteredEventAsyncTask extends
AsyncTask<String, Integer, Double> {
static EventController eventCtrl = new EventController();
public static ArrayList<Event> upcomingModel = new ArrayList<Event>();
public static ArrayList<Event> pastModel = new ArrayList<Event>();
public interface OnRoutineFinished { // interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public GetRegisteredEventAsyncTask(OnRoutineFinished callback) {
mCallbacks = callback;
}
public GetRegisteredEventAsyncTask() {
} // empty constructor to maintain compatibility
#Override
protected Double doInBackground(String... params) {
try {
upcomingModel = eventCtrl.getRegisteredUpcomingEvent(params[0]);
pastModel = eventCtrl.getRegisteredPastEvent(params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
if (mCallbacks != null)
mCallbacks.onFinish(); // call interface on finish
}
protected void onProgressUpdate(Integer... progress) {
}
}
In your onClick() method you could write something like:
new LoadViewTask().execute();
and the progress dialog will be shown in that page itself.
what are you doing man, just call your AsyncTask not the intent
public void onClick(View v)
{
new LoadViewTask().execute();
}
});
do your intent in postExecute
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
//START YOUR ACTIVITY HERE
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
Must read the documentation of AsynTask

To execute AsyncTask from onClick(DialogInterface dialog)

Currently I have two java class, 1 with AsyncTask and another one is with extend DialogFragment.
I would like to call CreateGroupTask(AsyncTask) in ChooseAddContact java class.
I have tried several recommended ways to execute the AsyncTask java but all failed.
Any recommendation or solution to that?
public class ChooseAddContact extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_add)
.setItems(R.array.contact_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0){
AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
**How should I CALL it here??
//new CreateGroupTask().execute();
//makegroup = new CreateGroupTask();
//makegroup.execute();
}**
}
});
return builder.create(); }
}
And
public class CreateGroupTask extends AsyncTask<Void, Void, String> {
private Context mContext;
private ProgressDialog pd;
public CreateGroupTask() {
}
public CreateGroupTask(Context mContext) {
super();
this.mContext = mContext;
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(mContext, null, "Creating group...");
}
#Override
protected String doInBackground(Void... params) {
String chatId = ServerUtilities.create();
if (chatId == null) return null;
try {
...
} catch (SQLException sqle) {}
return chatId;
}
#Override
protected void onCancelled() {
pd.dismiss();
}
#Override
protected void onPostExecute(String result) {
pd.dismiss();
if (result != null) {
Toast.makeText(mContext, "Group created " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mContext, "Group creation failed. Please retry later.", Toast.LENGTH_LONG).show();
}
}
}
In Dialog Fragment
To Start the async task you need context. In dialog Fragment you can get the context by calling getActivity(); or else you can get the context or activity reference in onAttach() lifecycle method of dialog fragment. Already parametrized constructor is there better to remove zero parametrized constructor.
new CreateGroupTask(getActivity()).execute();
(OR)
private Activity activity;
onAttach(Activity activity){
this.activity=activity;
//store this activity reference
}
//Then Call
new CreateGroupTask(activity).execute();
You can create an object of the class CreateGroupTask and execute wherever you want.
CreateGroupTask createGroupTask = new CreateGroupTask();
then
` if (which == 0){ AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
createGroupTask.execute();
// Or new CreateGroupTask().execute();
}`
try this and tell us if any error
What you are missing in AsyncTask is Context. you are using mContext in below code
pd = ProgressDialog.show(mContext, null, "Creating group...");
but you are not initializing that object in default constructor.
Use getActivity while calling task
new CreateGroupTask(getActivity()).execute();
Also remove following constructor from your code
public CreateGroupTask() {
}

AsycTask Throwing IllegalStateException - Fragment Not Attached To Activity

I have the following AsyncTask in my Android application. This AsyncTask is contained with within the OnCreate() method of a class that extends PreferenceFragment.
public class NotificationsPreferenceFragment extends PreferenceFragment {
private static Context context;
public NotificationsPreferenceFragment() {
}
public NotificationsPreferenceFragment(Context context) {
this.context = context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notifications);
getPreferenceManager().findPreference(getString(R.string.send_all_notifications))
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
class NotificationSendTask extends DialogAsyncTask {
public static final String TAG = "NotificationFragment";
public NotificationSendTask(Activity activity, String dialogMsg) {
super(activity, dialogMsg);
}
#Override
protected String doInBackground(String... params) {
String url = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString(getString(R.string.notification_web_service_url), getString(R.string.default_notification_web_service_url));
if (NetworkingHelper.isNetworkAvailable(getActivity())) {
NotificationDao notificationDao = new NotificationDaoImpl(DatabaseManager.getInstance(getActivity().getApplicationContext()), getActivity().getApplicationContext());
List<Notification> unsentNotificationList = notificationDao.findAllNotSent();
if (unsentNotificationList.size() != 0) {
NotificationSenderTask ns = new NotificationSenderTask(url, context);
try {
if (ns.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (unsentNotificationList)).get()) {
return getString(R.string.success);
}
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
} catch (ExecutionException e) {
Log.e(TAG, e.getMessage());
}
return getString(R.string.failed_to_send_notifications);
} else {
return getString(R.string.no_notifications_to_send);
}
} else {
return getString(R.string.no_connection_notifications);
}
}
public void onPostExecute(String result) {
super.onPostExecute(result);
if (dialog != null && dialog.isShowing()) {
dialog.hide();
}
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
}
NotificationSendTask notificationSendTask = new NotificationSendTask(getActivity(), "Sending unsent notifications...");
notificationSendTask.execute();
return true;
}
});
getPreferenceManager().findPreference(getString(R.string.export_notifications)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
NotificationExportTask notificationExportTask = new NotificationExportTask(NotificationsPreferenceFragment.this.getActivity(), 1);
notificationExportTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return true;
}
});
}
}
I am getting the following exception:
java.lang.IllegalStateException: Fragment NotificationsPreferenceFragment{416092f8} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:741)
at android.app.Fragment.getString(Fragment.java:763)
Can someone please explain to me why this is happening and suggest ways to fix this issue?
UPDATE:
Here is the code for the Activity:
public class SettingsActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
Since you are performing background task in your app. there is no guarantee that user will stay on same screen until task finishes so if user navigates to other screen or presses home button before task is completed; your fragment is detached from activity. So always make sure that you have fragment attached with the Activity.
try checking with
if (isAdded) {
//Do your UI stuff here
}
add above check wherever you get callback
Move your code from onCreate to onActivityCreated instead of trying to getActivity # onCreate.
That's because the fragment can be created when the activity is not yet ready, that's when you are trying to use it.
That is of course if you are adding the fragment to an activity like:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, new PreferenceFragment()).commit();

Java AsyncTask not showing progress on UI though publishProgress(progress)

In my android app, i am doing time consuming task extending AsyncTask, and want to display the progress in Toast messages. Toast messages are also displayed onPre() and onPost().
I am able to display Toast messages onPre() & onPost() but not able to show onProgressUpdate(Integer... progress).
Following is my code...
public class MainClass extends Activity {
public void Start(View view) {
DemoTasks runner = new DemoTasks(this);
runner.execute("Start");
}
private class DemoTasks extends AsyncTask<String, Integer, Integer> {
private Context context;
public DemoTasks(Context context){
this.context = context;
}
#Override
protected Integer doInBackground(String... params) {
try {
publishProgress(0);
doWork();
Thread.sleep(5000L);
publishProgress(100);
} catch (Exception localException) {
Log.d("POST", localException.getMessage());
}
return 100;
}
#Override
protected void onPostExecute(Integer result) {
Toast.makeText(context, "post", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPreExecute() {
Toast.makeText(context, "pre", Toast.LENGTH_SHORT).show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
Toast.makeText(context, "progress-" + progress, Toast.LENGTH_SHORT).show();
}
}
}
Also in my doInBackgroud(String...params) ...Thread.sleep is also not working.
As soon as onPre() gets executed, onPost() also executes after that!!!!
You can try this,
showProgress ();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
dialog.cancel();
Intent i=new Intent(getApplicationContext(),Main.class);
startActivity(i);
finish();
}
}, 3000); //number of seconds
private ProgressDialog dialog;
public void showProgress () {
dialog = new ProgressDialog(this);
dialog.setCancelable(true);
dialog.setMessage("Please wait");
dialog.show();}
Bascially,you can access the UI on any method, even In doinBackground you can access the UI using runOnUIthread.
here is one AsyncTask Example. This will show a peogress dialog while executing the task.
private class LoginProcessing extends AsyncTask<Object, Void, Void> {
private LoginCredentials myLoginCredentials;
private ProgressDialog progressDialog;
public LoginProcessing(LoginCredentials Credentials) {
super();
myLoginCredentials=Credentials;
progressDialog.setMax(100);
progressDialog.setMessage("Please Wait..");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setProgress(0);
progressDialog.show();
}
protected void onPreExecute (){
}
#Override
protected Void doInBackground(Object... arg0) {
// TODO Auto-generated method stub
//Code to do the process in background
return null;
}
#Override
protected void onProgressUpdate(Long... progress) {
// int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
progressDialog.setProgress(progress);
}
protected void onPostExecute(Void result){
progressDialog.dismiss();
//Your code after the process
}
}
You can call this Task as,
new LoginProcessing(loginCredentials).execute();
In this Example loginCredentials is the parameter I am passing to the AsyncTask. You can change it to your own parameter.

How to show "Loading" status in Android?

I'm making an Android application and it has to load some data though Internet (only some data-- not all). So when the data is loading, and the Internet connection is slow, I want to show a "Loading..." icon to the user.
So how can I do this? Show a "Loading..." icon while the data is being loaded in the background, and when its completely loaded, hide the icon?
Thanks in advance!
use Async Task for your status.
new SomeTask(0).execute();
/** Inner class for implementing progress bar before fetching data **/
private class SomeTask extends AsyncTask<Void, Void, Integer>
{
private ProgressDialog Dialog = new ProgressDialog(yourActivityClass.this);
#Override
protected void onPreExecute()
{
Dialog.setMessage("Doing something...");
Dialog.show();
}
#Override
protected Integer doInBackground(Void... params)
{
//Task for doing something
return 0;
}
#Override
protected void onPostExecute(Integer result)
{
if(result==0)
{
//do some thing
}
// after completed finished the progressbar
Dialog.dismiss();
}
}
Use AsyncTask along with progress dialog on task completion..That will do..
Use asynctask for Background operations, then display progress dialog like below
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
List<Message> titles;
private ListActivity activity;
//private List<Message> messages;
public ProgressTask(ListActivity activity) {
this.activity = activity;
context = activity;
dialog = new ProgressDialog(context);
}
/** progress dialog to show user that the backup is processing. */
/** application context. */
private Context context;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
List<Message> titles = new ArrayList<Message>(messages.size());
for (Message msg : messages){
titles.add(msg);
}
MessageListAdapter adapter = new MessageListAdapter(activity, titles);
activity.setListAdapter(adapter);
adapter.notifyDataSetChanged();
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Error", Toast.LENGTH_LONG).show();
}
}
protected Boolean doInBackground(final String... args) {
try{
BaseFeedParser parser = new BaseFeedParser();
messages = parser.parse();
return true;
} catch (Exception e){
Log.e("tag", "error", e);
return false;
}
}
}
}
In the onCreate method:
WebView mWebView;
ProgressDialog pgDiagWebView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
pgDiagWebView = ProgressDialog.show(CreateAccountWebView.this, "Loading", "Wait", true);
mWebView = (WebView) findViewById(R.id.registerWebView);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new ResgisterWebViewClient());
mWebView.loadUrl("http://www.google.com/");
}
class ResgisterWebViewClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
pgDiagWebView.dismiss();
}
}

Categories

Resources