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.
}
});
Related
I am trying to load progressBar as dialog while the client app send some data to server and dismiss the bar when data is received back from server.The below code has implemented this model.. with and interface being implemented inside an activity.
private void setup(){
ConnectionHandler connectionHandler = new ConnectionHandler() {
#Override
public void onSendData(){
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog = new ProgressDialog(SignupActivity.this);
Log.d("progress bar", "getData: true" );
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setTitle("Loading..");
progressDialog.setMessage("Please wait");
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.show();
}
});
}
#Override
public void onReceiveData(List<Model> model) {
//do nothing for now
LoginMessage message = (LoginMessage)model.get(0);
if(message.getUserCode() != 0){
//registration successfull prompt to verify code;
Log.d("LoginMessage", "onListUpdate: " + message.toJson());
Intent intent = new Intent(getBaseContext(), VerificationActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra(getString(R.string.login_message),message.toJson());
intent.putExtra("email", credentials.getEmail());
progressDialog.dismiss();
startActivity(intent);
}else{
//something went wrong;
}
}
#Override
public Class<? extends Model> getType() {
return LoginMessage.class;
}
};
connectivity = new Connectivity(this, Properties.LOCALHOST + Properties.REGISTRATION_PHP);
connectivity.setConnectionHandler(connectionHandler);
}
The setup method is called when activity is created and connectivity is responsible for calling the onSendData() and onReceiveData().Everything was working fine untill i decided to have progressBar to make client wait for the data to load. Here the error is thrown saying android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application. I followed the solution shown in the other similar problem but didn't worked for me.
Some advised to use
progressBar = new ProgressBar(Activity.this) instead of
progressBar = new ProgressBar(getApplicationContext()) or new ProgressBar(getBaseContext)
but none of them worked for me.What is this error actually is saying to me.
Why is this error thrown?? please help
I'm currently working on a android app in which I use asynctasks to carry out json rest request. I've got this working fine. I have also got a progress dialog being made visible on the preexecute then dismissing it on the postexecute all working fine. see code below.
#Override
protected void onPreExecute(){
Variables var = Variables.getInstance();
Variables.getInstance().showPd(ProgressDialog.show(Variables.getInstance().getContext(), var.getValue("loggingin_text"), var.getValue("pleasewait"), true, false));
}
protected void onPostExecute( JSONObject[] loginresponse ){
Variables.getInstance().dismisspd();
try {
JSONObject responseheader = loginresponse[0].getJSONObject("commonInputParameters");
if (responseheader.getString("status").equals("SUCCESS")) {
Variables.getInstance().setUsername( loginresponse[1].getString("username") );
Variables.getInstance().setSessiontoken(responseheader.getString("userSessionToken"));
delegate.onRequestCompletion( true );
} else {
delegate.onRequestCompletion(false);
}
}catch (JSONException je ) {
this.cancel( true );
}
}
final Button _loginBTN = ( Button ) findViewById(R.id.loginBTN );
_loginBTN.setText( vars.getValue( "loginbtn_text" ) );
_loginBTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Functions functions = Functions.getInstance();
if( functions.isNetworkAvailable(getApplicationContext())) {
if (functions.fullypopulated(new Object[]{_username, _password})) {
LoginRequest login = new LoginRequest(new responseInterface() {
#Override
public void onRequestCompletion(boolean successfulRequest) {
Variables.getInstance().dismisspd();
if ( !successfulRequest ) {
functions.showDialog(Variables.getInstance().getValue("login_err"), findViewById(R.id.input_username));
functions.clearEditText(new EditText[]{_username, _password});
functions.setError(new EditText[]{_username, _password});
} else {
Intent intent = new Intent(getApplicationContext(), NavigationHandler.class);
startActivity(intent);
finish();
}
}
#Override
public void onRequestCompletion(String requestResponse) {}
#Override
public void onRequestCompletion(int requestResponse) {}
#Override
public void onRequestCompletion(float requestResponse) {}
});
Map<String, String> loginDetails = new HashMap<String, String>();
loginDetails.put("username", _username.getText().toString());
loginDetails.put("password", _password.getText().toString());
login.execute(loginDetails);
} else {
functions.showDialog(Variables.getInstance().getValue("no_details"), findViewById(R.id.input_username));
functions.clearEditText(new EditText[]{_username, _password});
functions.setError(new EditText[]{_username, _password});
}
}
else {
functions.showDialog(Variables.getInstance().getValue("no_network"), findViewById(R.id.input_username));
}
}
});
The problem is that when I try to work in a time out into the async task the progress dialog shows but not until after it has completed and at which point I can't remove it.
This is how I'm trying to run it with a time out.
try{
login.execute(loginDetails).get( 5000, TimeUnit.MILLISECONDS );
}catch (InterruptedException ie ){
}catch (ExecutionException ee){
}catch (TimeoutException te ){
login.cancel(true);
}
Yes I know the catches are empty right now.
UPDATE:
Never mind looking at the get function again, it actually blocks the UI thread that is why the Progress Dialog isn't showing until the ASyncTask has completed. Is there anyway to implement a timeout feature?
Cancelling a task
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
From http://developer.android.com/reference/android/os/AsyncTask.html
Mind the bold pieces ... as to my understanding, you should dismiss the Dialog in onCancelled() in case of Timeout.
The question is how to communicate with an Android phone to a server, so that if the Activity is left and the call in the Activity was not successful to repeat the transaction once again automatically. Just now I use the AsyncTask of Android to communicate with the server:
new AsyncTask<String, Void, List<String>>() {
#Override
protected void onPreExecute(
showWaitDialog();
}
#Override
protected void onPostExecute(List<String> msgList) {
//here I put the handling after the POST ie. error and success handling
hideWaitDialog();
if (msgList.isEmpty() {
//success handling --> starting an new Activity
} else {
errorView.setText (...);
errorLayout.setVisibility (View.VISIBLE);
}
}
#Override
protected List<String> doInBackground(String... params) {
List<String> msgs = new ArrayList<String>();
try{
//for example submitting an JSONObject
JSONObject result = HttpUtils.sendHttpPost(
AppConstants.WEB_URL, jsonObject);
//error handling on the result
boolean hasErrors = JsonResult.isOk(result);
if (hasErrors) {
// adding errors to msgs list
String[] errorMessages = JsonResult.getErrorMessages (result,...);
fillList (msgs, errorMessages);
return msgs;
}
} catch (CommunicationError er) {
msgs.add (er...);
}
return msgs;
}
}
The problem with this approach is, that if I don't have a successful transmission of the data I must stay in the same Activity. Until now I show an error message to the user and he is in charge to submit by a button again the results to the server.
What I'm looking for is some Activity that remains persistent in the memory which runs later in the case that the transmission wasn't made.
As an application case I use this to dynamically upload pictures for a Waypoint in a map if I pressed that waypoint. In some case it can happens that the connection to the mobile service provider isn't available (mountains, forest, far apart from antenna). Then I want to leave the map Activity and switch to the detail view of this waypoint. In the success case I put the picture into my model classes and make an serialization. If the user clicks again on the same waypoint the picture is not loaded again. In the non success case I don't want to wait that the user clicks against on the waypoint to retrieve the image. In fact I need a background task, some sort of a queue that pictures of waypoints that are already visited on couldn't be retrieved are loaded until the communication part gives back a positive result and the image can be written into the model. The next time the user is pressing the Waypoint the picture will be then present.
Are there any best practices for making such a code implementation?
Is there any example around?
Is there a better way of doing this?
Yes, you need to Implement Intent Service for this requirement
According to the developers website
The IntentService class provides a straightforward structure for running an operation on a single background thread.
For complete details and working source code, Go through the Android Docs
Thanks to the answer of David.
I just read after the suggestion the tutorial at
[1] http://code.tutsplus.com/tutorials/android-fundamentals-intentservice-basics--mobile-6183
After my tests I prefered a Service (not an IntentService)
and created a service: SubmissionService
public class SubmissionIntentService extends Service {
private List<PendingMessage> pMsgList = new CopyOnWriteArrayList<PendingMessage>();
private Handler handler = new Handler();
private boolean hasAppStopped = false;
private Runnable runner;
public SubmissionIntentService() {
super();
Log.d (TAG, "Service created...");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PendingMessage pMessage = (PendingMessage) intent.getParcelableExtra(AppConstants.MESSAGE_OBJECT);
synchronized (pMsgList) {
pMsgList.add(pMessage);
}
if (runner == null) {
handler.postDelayed(runner = initializeRunnable(), 500);
}
return Service.START_NOT_STICKY;
}
private void runAsLongAppIsActive (Runnable runner) {
if (!hasAppStopped) {
handler.postDelayed (runner, SOME_INTERVAL_CONSTANT);
}
}
private Runnable initializeRunnable() {
Runnable result;
result = new Runnable() {
#Override
public void run() {
if (pMsgList.isEmpty()) {
runAsLongAppIsActive (this);
return;
}
PendingMessage[] pMArray = null;
synchronized(pMsgList) {
pMArray = pMsgList.toArray (new PendingMessage[pMsgList.size()]);
}
if (pMArray==null || pMArray.length==0) {
runAsLongAppIsActive (this);
return;
}
Log.d (TAG, "Message List size is actually :"+pMArray.length);
for (PendingMessage pM: pMArray) {
try {
JSONObject jsonMess = JSONSendMessage.buildOutput (pM);
JSONObject result = HttupUtils.sendHttpPost (WEB_URL, jsonMess);
boolean hasErrors = JSONResult.isOk (result);
if (hasErrors) {
//TODO: error handling in case of transmission
//don't remove the message from the queue
runAsLongAppIsActive(this);
return;
}
//remove pending transmission of the queue if success
synchronized (pMsgList) {
pMsgList.remove (pM);
}
//inform over receiver if activity is shown
Intent broadcastIntent = new Intent();
//put data in intent
sendBroadcast (intent);
//more important
WayPointModel model = ModelInstance.getWayPointModel();
model.addToModel (pM, result);
model.store();
} catch (Exception e) {
continue; //try to send other messages
}
}
runAsLongAppIsActive (this);
}
};
return result;
}
}
#Override
public void onDestroy() {
hasAppStopped = true;
handler.removeCallbacks (runner);
super.onDestroy();
}
}
Further I added a ResponseReceiver:
public class ResponseReceiver extends BroadcastReceiver {
public static final String ACTION_RESP = "MESSAGE_PROCESSED";
#Override
public void onReceive(Context context, Intent intent) {
//work in progress...
}
}
and in the Activity where I want to be informed about events:
public class SomeActivity extends Activity {
private ResponseReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new ResponseReceiver();
registerReceiver(receiver, filter);
...
}
}
and finally to send messages over Http:
Intent msgIntent = new Intent(this, SubmissionIntentService.class);
msgIntent.putExtra(...);
startService(msgIntent);
don't forget to declare the service in your manifest:
<service android:name="ch.xxx.app.service.SubmissionIntentService" />
Observations:
- I called the method startService(...) from different Activities. The constructor is only called once.
==> I have just on instance of the service for all Activities (exactly what I need).
What I don't get until now:
- Putting back data to the Activity. What is if the Activity is at the moment no shown?
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 am very confused, i am trying for two days to make animation on an image while my engine is thinking of a move (this is a game app). I execute the chooseMove() method inside AsyncTask object because it is a little heavy recursive function that may take some time,and also i want to rotate an hourglass image while the engine is thinking. and i tried to do it every way i know: another AsyncTask, Android's own animation class,handlers etc'. but no matter what i do it seems that i can't make it work. if i try to execute two threads at the same time,it only executes one of them, and the same thing happens with android own animation class. so i tried to use a progress dialog just to see that i am not getting crazy,and guess what.. same problem! I show the progress dialog in the onPreExecute() ,but the doInBackgroun() never gets done! the progress dialog take control over the whole app for some reason. how should i do it? i though that the progress dialog is meant for this kind of things. thx!
EDIT: this is the code of my async task class. as you can see, i am showing a progress dialog in the onPreExecute() ,and dismissing it in the onPostExecute. but the onPost never gets called because the doInBackground() never gets called either.
protected void onPreExecute() {
super.onPreExecute();
activity.setPlaying(true);
if (android.os.Build.VERSION.SDK_INT >android.os.Build.VERSION_CODES.GINGERBREAD) {
// only for gingerbread and newer versions
activity.invalidateOptionsMenu();
}
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Thinking...");
progressDialog.setIndeterminate(true);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
#Override
protected Integer doInBackground(Void... arg0) {
int engineWin = board.takeWin(board.getBoard(), engine.getNumberOfEngine());
int opponentWin = board.takeWin(board.getBoard(), engine.getNumberOfOpponent());
if(engineWin!=-1){
try{
Thread.sleep(500);
}
catch(Exception e){}
return engineWin;
}
else if(opponentWin!=-1){
try{
Thread.sleep(500);
}
catch(Exception e){}
return opponentWin;
}
else{
if(engine.isEnginesTurn()&&!Board.checkGameOver(board.getBoard())){
int[] newBoard = new int[42];
System.arraycopy(board.getBoard(), 0, newBoard, 0, 42);
return engine.chooseMove(engine.isEnginesTurn(),newBoard,-500001,500001,0,4).getMove();
}
else{
return -1;
}
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
progressDialog.dismiss();
if(result!=-1){
ballAnimTask = new BallAnimTask(activity,boardView,board,engine);
ballAnimTask.execute(findSlotNumberByIndex(result));
}
}
this is the recursive chooseMove() i am calling in doInBackground(). before i tried to show the progress dialog,everything worked just fine. there is no problem with this function or any other function for that matter. only when i tried to do animations or dialogs at the same time,i got issues. the chooseMove() is physically on another class and i am only calling it from the AsyncTask. maybe this is the problem??
public Best chooseMove(boolean side,int[]board,int alpha,int beta,int depth,int maxDepth){
Best myBest = new Best();
Best reply;
int num;
if(Board.checkGameOver(board)||depth==maxDepth){
myBest.setScore(returnPositionScore(board));
return myBest;
}
if(side){
myBest.setScore(alpha);
num = numberOfEngine;
}
else{
myBest.setScore(beta);
num = numberOfOpponent;
}
ArrayList<Integer> availableMoves = new ArrayList<Integer>();
availableMoves = searchAvailableMoves(board);
for(int move:availableMoves){
board[move] = num;
reply = chooseMove(!side,board,alpha,beta,depth+1,maxDepth);
board[move] = 0;
if(side&&reply.getScore()>myBest.getScore()){
myBest.setMove(move);
myBest.setScore(reply.getScore());
alpha = reply.getScore();
}
else if(!side&&reply.getScore()<myBest.getScore()){
myBest.setMove(move);
myBest.setScore(reply.getScore());
beta = reply.getScore();
}
if(alpha>=beta){
return myBest;
}
}
return myBest;
}
If you want to perform any UI related operation from within an AsyncTask you need to call the AsyncTask publishProgress method. This will invoke an onProgressUpdate callback in the main UI thread and so you can then safely perform your UI related operations there.
Obviously any code in the onProgressUpdate can't block, though, since you are now back in the main UI thread. But you can update a status bar, for example, and then wait for the next onProgressUpdate callback before you update it again.
Just for some inspiration, here is the general code format that I have used successfully to show a horizontal progress bar which updates while a background task is running. I know it doesn't answer your exact question, but I hope it helps you to find your solution.
ProgressDialog myProgressDialog;
private void someFunctionThatStartsTheAsyncTask()
{
new myBackgroundTask.execute(someIntegerArgument);
}
private class myBackgroundTask extends AsyncTask<Integer, Integer, Boolean>
{
protected void onPreExecute()
{
myProgressDialog = new ProgressDialog(myContext);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myProgressDialog.setTitle("Doing something in background...");
myProgressDialog.setMessage("Please wait...");
myProgressDialog.setCancelable(false);
myProgressDialog.setIndeterminate(false);
myProgressDialog.setMax(100);
myProgressDialog.setProgress(0);
myProgressDialog.show();
}
protected Boolean doInBackground(Integer... params)
{
int someVariable = params[0];
boolean success;
for (whatever loop conditions)
{
// some long-running stuff, setting 'success' at some point
...
publishProgress(newPositionForProgressBar);
}
return success;
}
protected void onProgressUpdate(Integer... progressPosition)
{
myProgressDialog.setProgress(progressPosition[0]);
}
protected void onPostExecute(Boolean result)
{
myProgressDialog.dismiss();
if (result)
{
//doInBackground returned true
}
else
{
//doInBackground returned false
}
}
}