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().
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 have an issue when I am trying to set text from a last item of a listView into text View which is in the MainActivity. It crashes during running time on “NullPointerException” because I think that that when I’m calling it in MainActivity, It didn’t finish to download on the ListView so when the MainActivity first launched, the listView did not finish his work and the functions getCount(),getItem() and my function getLastElement() are still null.
The issue is that I am not very good with dealing with Thread (Wait(), notify(),..)
Can you please help me with all this?
Here is my code and my LogCat :
public class MainActivity extends Activity implements OnClickListener{
private static Context mContext;
public Button mExit, mHistory, mRating;
public TextView mSignal;
HistoryAdapt myAdapter;
HistoryItems m_myLastItem;
ArrayList<HistoryItems> m_myListItem;
Runnable m_run;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.mContext=getApplicationContext();
mExit=(Button)findViewById(R.id.ExitButton);
mExit.setOnClickListener(this);
mHistory=(Button)findViewById(R.id.HistoryButton);
mHistory.setOnClickListener(this);
mRating=(Button)findViewById(R.id.RateButton);
mRating.setOnClickListener(this);
mSignal=(TextView)findViewById(R.id.SignalOfTheDayTV);
//### SET LAST ELEMENT INTO TEXTVIEW
m_myListItem = new ArrayList<HistoryItems>();
myAdapter= new HistoryAdapt(mContext, m_myListItem);
new Thread(
new Runnable(){
#Override
public void run(){
try{
///Need to wait until the data to be downloaded inside HistoryAdapt so it can show the last element from the ListView here
HistoryParser parser = new HistoryParser();
parser.parse(getInputStream(HistoryAct.RSS_LINK));
} catch (XmlPullParserException e) {
Log.w(e.getMessage(), e);
} catch (IOException e) {
Log.w(e.getMessage(), e);
} finally {
//notify that the data finished to download
MainActivity.this.runOnUiThread(
new Runnable(){
public void run(){
m_myLastItem = myAdapter.getLastElement();
//set last signal into TextView
mSignal.setText(m_myLastItem.getTitle());
}
}
);
}
}
}
).run();
//#RATER
// AppRater.app_launched(this);
// AppRater.showRateDialog(this, null);
//Get a Tracker (should auto-report)
((AppManager) getApplication()).getTracker(AppManager.TrackerName.APP_TRACKER);
}//oncreate
private InputStream getInputStream(String link) {
try {
URL url = new URL(link);
return url.openConnection().getInputStream();
} catch (IOException e) {
Log.w(Constants.DATA, "Exception while retrieving the input stream", e);
return null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static Context getAppContext(){
return MainActivity.mContext;
}
public void ExitState(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("You're about to quit Signals4Trading");
builder.setIcon(R.drawable.five);
//builder.setMessage("Your device has been registered successfully. You'll receive signals very soon.");
builder.setMessage("Are you sure you want to quit?");
builder.setCancelable(false);//can't click on the background of the activity
builder.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),"See you soon", Toast.LENGTH_LONG).show();
finish();
}//OnClickListener PositiveButton
});//anonymous class PositiveButton
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),"Enjoy your visit", Toast.LENGTH_LONG).show();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}//ExitState
public void goToHistoryActivity(){
Intent intent = new Intent(MainActivity.this, HistoryAct.class );
startActivity(intent);
}
public void rateApp(){
Intent intent = new Intent(MainActivity.this, Rate.class);
startActivity(intent);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()){
case R.id.ExitButton:
ExitState();
break;
case R.id.HistoryButton:
goToHistoryActivity();
break;
case R.id.RateButton:
rateApp();
break;
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
//Get an Analytics tracker to report app starts & uncaught exceptions etc.
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
//Stop the analytics tracking
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}//MainActivity
package com.Signals4Trading.push.android;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.os.StrictMode;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class HistoryAdapt extends BaseAdapter {
private final List<HistoryItems>items;
private final Context context;
public HistoryAdapt(Context context,List<HistoryItems>items){
this.context=context;
this.items=items;
}//constructor
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int id) {
// TODO Auto-generated method stub
return id;
}
//###FUNCTION THAT RETURN LAST ELEMENT
public HistoryItems getLastElement(){
return items.get(items.size()-1);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(context, R.layout.historyitems, null);
holder = new ViewHolder();
holder.itemTitle = (TextView) convertView.findViewById(R.id.itemTitleTV);
holder.itemDate=(TextView) convertView.findViewById(R.id.itemDateTV);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.itemTitle.setText(items.get(position).getTitle());
holder.itemDate.setText(items.get(position).getDate());
}
return convertView;
}
class ViewHolder {
TextView itemTitle;
TextView itemDate;
}
}
//HistoryAdapt
11-13 15:18:34.702: E/AndroidRuntime(7737): FATAL EXCEPTION: main
11-13 15:18:34.702: E/AndroidRuntime(7737): Process: com.Signals4Trading.push.android, PID: 7737
11-13 15:18:34.702: E/AndroidRuntime(7737): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.Signals4Trading.push.android/com.Signals4Trading.push.android.MainActivity}:
java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1
11-13 15:18:34.702: E/AndroidRuntime(7737): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
Your onCreate() call in the Activity is calling:
m_myLastItem= HistoryAdapt.getLastElement();
But, the constructor for HistoryAdapt has not been called yet, and that is where you initialize the static field items within it. I would recommend rethinking this class and its usage as you're using it in an instance manner but have it partially coded as if it is a static class. A good rule of thumb to follow is don't make your static methods dependent on the class being constructed. At that point it's just an instance method.
Looks like you're trying to perform an asynchronous operation using a runnable, then before the asynchronous operation is completed you're trying to use the value it is supposed to set. So I'm assuming you're trying to create a background thread that waits for the data and updates/notifies the UI/UI-thread when it's done loading. This would mean that the asynchronous operation is created and started by the UI-thread during OnCreate and while it is running the UI-thread can happily go on executing the OnCreate method and loading the UI etc.
First of all, it looks like you're creating a runnable but not running it. If you want to run the runnable in a different (asynchronous) thread, try this:
new Thread(
new Runnable()
{
#Override
public void Run()
{
//your code here
}
}
).Run();
*note: Translated this from C#, may not be 100% correct (caps?) but should be really easy to get working.
It's not entirely clear from your code but I assume the code in your runnable fills the HistoryAdapt class with data. Be careful not to create concurrency issues this way. If two threads are trying to access the same object at the same time you may have problems so be sure to properly "lock" objects before using them in seperate threads. In java you can use a "synch" clause to do this:
synchronized(this){
this = newvalue;
}
This makes sure that while the code inside the braces is executing the "this" object cannot be accessed by other threads. Other threads will then wait untill the code is executed and the object is released before continuing.
Secondly, you should be aware that the runnable/thread you've created is basicly a thread that is run once and then disposed (so not a dedicated thread). In this case monitor/wait is not really necessary. You could simply include the code that updates the UI (mSignal.setText(m_myLastItem.getTitle());) in the finally clause of your try/catch statement. Be sure to use the runOnUiThread method when you're trying to update/edit UI-elements from seperate threads like so:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
m_myLastItem = HistoryAdapt.getLastElement();
//set last signal into TextView
mSignal.setText(m_myLastItem.getTitle());
}
});
This way, the thread is created in OnCreate, does its job seperately from the UI-thread, then updates the UI as soon as it is done. One possible problem you might have is that mSignal.setText() could get called at a moment when the UI isnt ready to be updated, not sure this will really be a problem in this case though. Also, when using this technique in other places you may need a reference to your activity to use inside your thread (you can't always get a reference from the place where you're defining the thread/runnable), that's easy enough, just make a static reference to your activity somewhere in your app and reference that (i prefer an App_Session class for static variables used app-wide).
Hope I understood the question correctly and this helps. In any case, good luck!
*Edit: Full example
new Thread(
new Runnable()
{
#Override
public void run()
{
if(!HistoryAdapt.hasBeenInitiated)
{
try
{
///Need to wait until the data to be downloaded inside HistoryAdapt so it can show the last element from the ListView here
HistoryParser parser = new HistoryParser();
parser.parse(getInputStream(HistoryAct.RSS_LINK));
} catch (XmlPullParserException e) {
Log.w(e.getMessage(), e);
} catch (IOException e) {
Log.w(e.getMessage(), e);
} finally {
//notify that the data finished to download
MainActivity.this.runOnUiThread(
new Runnable()
{
public void run()
{
if (!HistoryAdapt.hasBeenInitiated)
{
m_myLastItem = HistoryAdapt.getLastElement();
//set last signal into TextView
mSignal.setText(m_myLastItem.getTitle());
}
}
}
);
}
}
}
}
).run();
Could not test this unfortunately since i can't run Java (i use xamarin), should be correct though, maybe the #override isnt needed and im not sure if it's supposed to be 'Run' or 'run'. I'm sure you'll figure that out though ;)
Thread run = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
run = new Thread( new Runnable(){
public void run(){
if(!HistoryAdapt.hasBeenInitiated){
try {
///Need to wait until the data to be downloaded inside HistoryAdapt so it can show the last element from the ListView here
HistoryParser parser = new HistoryParser();
parser.parse(getInputStream(HistoryAct.RSS_LINK));
} catch (XmlPullParserException e) {
Log.w(e.getMessage(), e);
} catch (IOException e) {
Log.w(e.getMessage(), e);
}finally{
//notify that the data finished to download
}
}
}
});
run.start();
run.join();
use this but it will wait until your run thread finish.
I have a asyc task that stores objects in cloudmine. Now I want to wait for the confirmation from cloudmine that the objects are stored. But before I get the conversation the postExecute method starts, which gives the wrong toast message. Main problem is that the cloudmine task itself is async and so I want doInBacground to wait for the cloudmine async to finish. Nothing I have tried has worked.
Here is the code:
public class createCloudmineLot extends AsyncTask<Void,Void,Boolean>
{
private boolean success;
private boolean inputFault;
protected void onPostExecute(Boolean arg0)
{
System.out.println("postExecute sucess value: " + success);
if(inputFault)
{
t = Toast.makeText(AddParking.this, "No Input!Please press enter after each input",Toast.LENGTH_LONG);
t.show();
}
else
if(arg0)
{
t = Toast.makeText(AddParking.this, "Parking Lot was added:" + success,Toast.LENGTH_LONG);
t.show();
}
else
{
t = Toast.makeText(AddParking.this, "Unable to add Parking Lot" + success,Toast.LENGTH_LONG);
t.show();
}
return;
}
#Override
protected Boolean doInBackground(Void... params)
{
// TODO Auto-generated method stub
CMApiCredentials.initialize(APP_ID, API_KEY, getApplicationContext());//initializing Cloudmine connetion
SimpleCMObject parkingLot = new SimpleCMObject();
if(name.equals("") | address.equals("") | pricing.equals("") | hours.equals("") | latitude.equals("") | longitude.equals(""))
{
inputFault = true;
return null;
}
parkingLot.add("name", name);
parkingLot.add("address",address);
parkingLot.add("pricing",pricing);
parkingLot.add("hours",hours);
double lat = Double.parseDouble(latitude);
double lon = Double.parseDouble(longitude);
CMGeoPoint locationCoordinates = new CMGeoPoint(lat,lon);
parkingLot.add("location",locationCoordinates);
parkingLot.save(new ObjectModificationResponseCallback()
{
public void onCompletion(ObjectModificationResponse response)
{
success = response.wasSuccess();
System.out.println("doInbackground: "+ success);
}
});
return success;
}//end of doBackground
}//end on AsyncTask
This is when I try with Broadcast Receivers. Using the receiver, nothing happens.
public class EditParking extends Activity
{
private ListView lotList;
private ArrayList<String> lots;
private ArrayAdapter<String> arrayAdpt;
private class ReceiveBroadcastActivity extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
System.out.println("received");
ArrayList<String> lots = intent.getStringArrayListExtra("ParkingLots");
ListView lotlist = (ListView)findViewById(R.id.lotList);
ArrayAdapter<String> arrayAdpt = new ArrayAdapter<String>(EditParking.this,android.R.layout.simple_list_item_1,lots);
lotList.setAdapter(arrayAdpt);
System.out.println("lots: "+ lots);
}
};
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.editparking_layout);
lotList = (ListView)findViewById(R.id.lotList);
lots = new ArrayList<String>();
lots.add("hello");
arrayAdpt = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,lots);
lotList.setAdapter(arrayAdpt);
arrayAdpt.setNotifyOnChange(true);
CMApiCredentials.initialize(APP_ID, API_KEY, getApplicationContext());//initializing Cloudmine connection
CMStore store = CMStore.getStore();
store.loadAllApplicationObjects(new CMObjectResponseCallback()
{
public void onCompletion(CMObjectResponse response)
{
for(CMObject object : response.getObjects())
{
// do something with each object
SimpleCMObject lot = (SimpleCMObject)object;
String lotInfo = lot.getString("name") + "\n" + lot.getString("address") +
"\nPrice: " + lot.getString("pricing") + "\nHours: " + lot.getString("hours");
System.out.println(lotInfo);
}
Intent broadcastIntent = new Intent();
lots.add("world");
broadcastIntent.putStringArrayListExtra("ParkingLots", lots);
broadcastIntent.setAction("com.cs275.findparking.broadcast");
sendBroadcast(broadcastIntent);
}
The problem is that the call you are doing inside the doInBackground is also an asynchronous call, you need to realize that by the time the execution thread reaches the end of doInBackground and returns an object, the onPostExecute will be called, so basically the problem in your case is that since your call is also asynchronous, its not blocking the thread and it moves inmediately to the end of the doInBackground method and the "callback" you receive from that call is executed way later than the whole asynctask did it's job, so, that said there's different ways to approach the issue.
1.- You could force the worker thread in doInBackground to wait for your callback to be executed(this requires a perfect understanding of java threads and the wait/notify methods)
2.- A simple approach would be, not to rely on onPostExecute method, and in stead send a Broadcast Receiver message from the callback method of your call, which will be handled in your activity whenever is done..
Regards!
I have three images with me and i want them to appear on first layout xml like a splash view so that they can be viewed only once i.e that activity will be called only once when app get's installed or if app get's a new update otherwise app should always start from the Second activity, i don't know how should i begin with this :
Can any one tell me any idea how this can be done.
To show splash for only once.
Next part of this question is here
Coding will be much appreciated.
Save a flag in the Preferences when you start up the application, after you've done the welcome screen stuff. Check for this flag before you show the welcome screen. If the flag is present (in other words, if it's not the first time), don't show it.
In your activity:
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
// the code below will display a popup
String whatsNewTitle = getResources().getString(R.string.whatsNewTitle);
String whatsNewText = getResources().getString(R.string.whatsNewText);
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(whatsNewTitle).setMessage(whatsNewText).setPositiveButton(
R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Try this :
public class MainActivity extends Activity {
private Thread mSplashThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
final MainActivity sPlashScreen = this;
mSplashThread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(4000);
}
} catch (InterruptedException ex) {
}
finish();
Intent intent = new Intent();
intent.setClass(sPlashScreen, StartNewActivity.class);// <-- Activity you want to start after Splash
startActivity(intent);
}
};
mSplashThread.start();
} catch (Exception e) {
}
}
#Override
public boolean onTouchEvent(MotionEvent evt) {
try {
if (evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized (mSplashThread) {
mSplashThread.notifyAll();
}
}
} catch (Exception e) {
}
return true;
}
}
you put an Image in splash.xml to show
to do this you have to detect the first launch of your application. To do so you can store a boolean value as #Nirav suggested.
And for the splash screen, You can consider using Fragments and ViewPager to create an activity which will only be shown for the first time
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.
}
});