I have an update database operation, that has an activity, which keeps updating the percentage and it runs inside an AsyncTask.
Inside doInBackground() I call the controller that updates the database and keep updating the percentage on the activity, however, if I press home button or back button, the operation is cancelled. What u suggest me to do?
I was trying to start a Service inside doInBackground() so it would run in background, but it looks like its not working.
My code looks like this:
public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer>
{
@Override
public void onPreExecute()
{
mCustomProgressBar.startAnimation();
}
@Override
public Integer doInBackground(Void... params)
{
return mController.updateDatabase();
}
@Override
public void onPostExecute(Integer result)
{
mCustomProgressBar.stopAnimation();
// finish the activity
}
@Override
public void onProgressUpdate(Integer... value)
{
updatePercentageValue(value[0]);
}
public void callPublishProgress(Integer value)
{
publishProgress(value);
}
}
And inside the controller I call the method callPublishProgress(value)
passing the current percentage value, so it will publishProgress(value)
in the UI.
I was debugging, and I pressed the home/back button, and it just stopped running the worker thread.
Another solution I tried, was starting a Service to run in background no matter the user press home/back button or not, so I thought, and the Service would make a call to the controller method that does the work, and it would call the callPublishProgress(value)
to update the percentage value on the UI anyways.
However, what was happening is, the code reach doInBackground()
and start the service, but it goes to onPostExecute()
immediately, it just didn't wait the service to finish(of course!). So it gives a NullPointerException
. I thought of making a loop inside doInBackground()
with a flag set in the Service, so it would leave this loop while the service hasn't been finished (I was using an IntentService), but it didn't work anyways.
I thought of using a Timer too. But I don't know.
I was reading the articles in documentation about Threads, etc. And it suggests using AsyncTask
, just as I was trying to do. It also talks about runOnUiThread(Runnable)
.
Anyways what I need is to make an operation in background(probably using an IntentService), so no matter if the user press the home button, it will keep running, but it must update the percentage on the UI, and when the user leave the screen and back to it, it shows the current percentage value updated in the screen.
What is the best solution for my case?
Thanks.
Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml. In the above code, we have taken text view, when user gets the data from intent service it will update.
In this case, to update the UI from a background thread, you can create a handler attached to the UI thread, and then post an action as a Runnable : Handler handler = new Handler(Looper. getMainLooper()); handler. post(new Runnable() { @Override public void run() { // update the ui from here } });
You're updating the UI from a background thread. Don't do that. But the runtime is not required to provide a safety system that prevents or detects your error. It is not required to produce an error when you do something that you shouldn't be doing in the first place.
The updateUI() method of the BackgroundFetchUpdateUIEvent interface updates the title and icon in the user interface to show the status of a background fetch. This method may only be run once, to notify the user on a failed or a successful fetch.
public class MyServce extends Service{
public static final String BROADCAST_ACTION = "com.myapp";
Intent intent;
private final Handler handler = new Handler();
@Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
@Override
public void onStart(Intent intent, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DoYourWorking();
handler.postDelayed(this, 1000); // 1 seconds
}
private void DoYourWorking() {
........
........
intent.putExtra("key", progress);
sendBroadcast(intent);
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
Now in your Activity register broadcast to service
private BroadcastReceiver brodcast = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//intent.getWhatever
// update your progress
//progressbar.setProgress
}
register broadcast
registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION));
This worked for me. I started a background service on a thread that just fetches the values and updates an object in a singleton.
In the view controller, I start a timer that keeps updating the view by fetching data from the object in singleton.
I had a little problem understanding your entire question text, so I'm not sure if you have tried this. But this is what worked. Also, the service was started with START_STICKY
Use an IntentService (which is a Service on a thread of its own), and Handler to pass the data back to the Activity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With