AsynTask Never Runs in IntentService - java

I am trying to use following code:
public class SeparateProcessService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener
{
public SeparateProcessService() {
super("IntentService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
new UploadData().execute();
}
}
When the line of asynctask is executed it is either skipped by compiler or ignored.
any one guide me what could be the issue? i am actually trying to upload data to api through intentservice.
any help would be appreciated.

AsyncTask.execute() runs asynchronously. If you want to block onHandleIntent() until the AsyncTask completes, you can use new UploadData().get(). Hopefully you're not doing anything in onPreExecute or onPostExecute, because those won't get called.
I'd recommend avoiding AsyncTask in general and follow the user137021's advice and put the AsyncTask.doInBackground code directly in the IntentService.

Related

How to wait for the service to load before starting the activity

The Service class will load a library and it takes about 4-5 seconds for the library to become ready. What is the best way to make MainActivity to keep checking on the status of a static boolean in Service class and do something when it's ready? I looked around and knew that using busy wait loop is bad.
The outline of my planned MainActivity is
onCreate - start the service
onResume - show the splash screen until a specific boolean in Service become true then switch to another fragment
You could use a broadcast receiver from the Service to your MainActivity which triggers a method inside the MainActivity... instead of constantly checking a static bool in the service.
But you want to be very sure to handle cases where it never loads for whatever reason, otherwise users will be staring at a splash screen forever.
Simple solution is Broadcast Reciever Try this
BroadcastReceiver broadCastNewMessage = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do your stuff here
}
};
Now in onCreate() register this
registerReceiver(this.broadCastNewMessage, new IntentFilter("bcNewMessage"));
And in onDestroy()
unregisterReceiver(broadCastNewMessage);
Now Call this method from the service class where u want to update the activity
sendBroadcast(new Intent().setAction("bcNewMessage"));

Should DialogFragment be called through AsyncTask class?

I read many guides but I'm still confused.
Somewhere I read that the "activity flow" should not be interrupted by a DialogFragment, so you should call DialogFragment inside a AsyncTask Class inside the Activity Class.
In other guides I saw DialogFragment being called from the Activity Class without using AsyncTask.
So my question is: should DialogFragment be called only through AsyncTask class?
This is the way I did so far; the Activity class code:
public class LunchActivity extends AppCompatActivity {
....
public void callDialog(){
class ShowInfoToUser extends AsyncTask<Bundle, Void, Bundle> {
...
#Override
protected Bundle doInBackground(Bundle... args) {
...
}
#Override
protected void onPostExecute(Bundle resultBundle) {
DialogFragment permissionDialogManager= permissionDialogManager.newInstance(messageBundle);
permissionDialogManager.show(activity.getSupportFragmentManager(), "Permission Dialog");
}
}
}
This is the class that extends DialogFragment:
public class PermissionDialogManager extends DialogFragment {
public static PermissionDialogManager newInstance(Bundle bundle) {
PermissionDialogManager frag = new PermissionDialogManager();
frag.setArguments(bundle);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
}
}
Thank you
The code inside AsyncTask's onPostExecute method execute in the UI Thread. In the example you have provided, there is not difference if you use AsynTask or not, because the code will be executed in the UI Thread.
Maybe in the example you have seen, they process some information in the AsyncTask's doInBackground method (that execute in separate thread) and later in the onPostExecute method they use the previous information to invoke the DialogFragment.
How to know when should you run code in the UI Thread?
Processes and Threads
When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.
As the Dialog will interrupt the user, I see no reason to put it in an AsyncTask. The dialog is not supposed to take a huge amount of time to generate itself.

BroadcastReceiver has onReceive() called unexpectedly

I have an app in which I want to perform lookup some data every, say, 15 mins. I have a service that I start with an alarm, but I also want to make sure that there is a network connection before I start looking.
To do this I think I should use a BroadcastReceiver to watch for changes to the network state. I have wrapped a broadcast receiver to help with this:
public abstract class NetworkMonitor extends BroadcastReceiver
{
boolean mDoingStuff;
public abstract void doStuff();
public NetworkMonitor()
{
mDoingStuff = false;
IntentFilter networkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
MyApp.getContext().registerReceiver(this, networkStateFilter);
}
#Override
public void onReceive(Context context, Intent intent)
{
// network state changes, you can process it, information in intent
ConnectivityManager cn = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = ConnectivityManagerCompat.getNetworkInfoFromBroadcast(cn, intent);
// Only use Wifi Connections for updating this
if (info.isConnectedOrConnecting() && !mDoingStuff)
{
mDoingStuff = true;
doStuff();
}
}
}
I then use that in a service like:
public class WidgetUpdateService extends Service
{
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// Build the async task to get the data
final MyAsyncTask mTask = new MyAsyncTask();
// Register an interest in when the network changes
new NetworkMonitor(false)
{
public void doStuff()
{
mTask.execute();
}
};
// Make sure that if we get shut down then we get started again correctly.
return START_REDELIVER_INTENT;
}
protected class MyAsyncTask extends AsyncTask<Void, Void, Void>
{
public MyAsyncTask()
{
}
#Override
protected Integer doInBackground(Void... arg0)
{
// do work
}
#Override
protected void onPostExecute(Integer result)
{
WidgetUpdateService.this.stopSelf();
}
#Override
protected void onCancelled(Integer result)
{
WidgetUpdateService.this.stopSelf();
}
}
}
Where MyAsyncTask is an inner class that will cause the service to stopSelf() when it has completed.
This kinda works but:
I'm getting (according to logcat) far more calls to NetworkMonitor.doStuff() than I would expect. It seems that even when the service has been stopped (after the async task has finished correctly) the NetworkMonitor instance is still being receiving intents about changes to the network state. Why is this?
Do I need to have a variable to store the NetworkMonitor() instance in the service, or can I just have an anonymous instance like this? Looking at the docs the BroadcastReceiver should clear itself up after onReceive() has finished.
Why do I need NetworkMonitor.mDoingStuff? I'm guessing that if I can work out why the NetworkMonitor is not clearing itself up after onReceive() has finished then I may not need it any more?
Is this a sensible way of doing this or am I asking for trouble?
Please let me know if you need any more info, I'll be happy to supply it.
This kinda works
It's ghastly code, IMHO.
It seems that even when the service has been stopped (after the async task has finished correctly) the NetworkMonitor instance is still being receiving intents about changes to the network state. Why is this?
Because you never unregister the receiver. It will keep going -- and leaking memory like a sieve -- until your process is terminated.
Do I need to have a variable to store the NetworkMonitor() instance in the service, or can I just have an anonymous instance like this?
You need to have an instance so you can unregister it later. Registration and unregistration of the receiver should be done by the service; your register-the-receiver-in-its-constructor is part of what makes your code ghastly IMHO.
Looking at the docs the BroadcastReceiver should clear itself up after onReceive() has finished
A manifest-registered BroadcastReceiver lives for a single broadcast. A BroadcastReceiver registered via registerReceiver() lives until unregisterReceiver().
Why do I need NetworkMonitor.mDoingStuff?
You have bigger problems.
Is this a sensible way of doing this
Not really.
First, you will crash on your second broadcast, as you cannot execute() an AsyncTask instance multiple times.
Second, see the aforementioned failing-to-unregister issues.
Third, if you want to have a service that does one thing, then goes away, use an IntentService.
So, let's roll all the way back to the top:
I have an app in which I want to perform lookup some data every, say, 15 mins. I have a service that I start with an alarm, but I also want to make sure that there is a network connection before I start looking.
The right way to do this is:
Have your AlarmManager event route to a BroadcastReceiver. This is particularly important if you are using a _WAKEUP alarm type, as such events are only reliable if you use a BroadcastReceiver PendingIntent.
In that BroadcastReceiver, in onReceive(), if you have a network connection, send a command to an IntentService to do the work (and, if you are using a _WAKEUP alarm type, consider my WakefulIntentService, so the device stay awake while you're doing this).
If, instead, there does not appear to be a network connection, have your BroadcastReceiver enable another manifest-registered BroadcastReceiver set up to watch for CONNECTIVITY_ACTION events -- use PackageManager and setComponentEnabledSetting() for this.
In the CONNECTIVITY_ACTION BroadcastReceiver, in onReceive(), if you determine that you now have a network connection, kick off your IntentService (same as what you would do from the AlarmManager receiver if you already had a connection).
In the IntentService/WakefulIntentService, do your work in onHandleIntent(). This already has a background thread and will already call stopSelf() when there is no more work to be done.
In the IntentService/WakefulIntentService, in onDestroy(), disable the CONNECTIVITY_ACTION BroadcastReceiver via PackageManager and setComponentEnabledSetting(), returning you to your original state.
This way:
You don't leak memory, as you are doing here.
You don't have to mess with threading code, as you are doing here.
You don't have to worry about whether or not your process gets kicked out of memory in between the alarm and gaining connectivity.
If connectivity is blocked for some time (e.g., airplane mode), you don't register N receivers and set up N AsyncTasks, as you are doing here. Instead, you will get control again whenever connectivity changes occur in the future after your alarm has gone off.

Running an activity in the background

I have an activity that send some details to my db, but when I click the back button it stops.
Is it possible to make it run on the background?I heared that using a Service could solve that issue but since all of my classes are wrriten as Activities I would like to know if it's possible.
It's can't be done with some code on the onStop method?
Heey,
Create a new class that extends of Service.
Add the necessary overrides.
#Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
//this service will run until we stop it
// This will execute when the service starts
return START_STICKY; //makes it sticky to keep it on until its destroyd
}
#Override
public void onDestroy()
{
super.onDestroy();
// when the service is destroyd
}
You can start a service with:
stopService(new Intent(getBaseContext(), ServiceClassName.class));
You can stop a service with:
stopService(new Intent(getBaseContext(), ServiceClassName.class));
Hope this helps :)
You mentioned that all of your classes are written as Activities, which I am assuming means you have your application logic embedded with your user interface logic. This is generally not a good practice - you should try and migrate application specific code to a separate class. By having this functionality outside your user interface, your application will benefit in numerous ways.
To answer your question, it is possible to have your application perform functions in the background by subclassing Service. Take a look here for a great explanation.
You will have to override the onBackPressed method to do what you want. If you want to "hide" the activity (so the user sees that it 'closes') you can call the moveTaskToBack method.
You should write a Service that the Activity communicates with using intents. Thus it should send the data to the service for it to send to the database, then the service can inform the activity. When the Activity listens to events from the Service, you are implementing the Observer pattern (Listeners in Java and Android and many other event processing systems).
You can also poll the service, but that is not the preferred pattern for getting status updates.

Create New Thread - Android

I'm trying to implement a looper so I can create a thread for sending GPS coordinates to a database. I'm new to Java and this is all really confusing, but maybe you can help. The following class method is called by the main activity when a button is pressed. The method finds the GPS location and then sends it to a different class's method that sends the latitude and longitude (along with the user id) to a database. I'm having trouble with my app slowing down and freezing at times, so it appears I need to implement some way to create a new thread for this process. Any ideas. I'm a noob so be gentle. Here is my code:
public class LocationActivity extends Thread{
private LocationManager locManager;
private LocationListener locListener;
public void startLocation(Context context, String usr_id2)
{
final String usr = usr_id2;
//get a reference to the LocationManager
locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//checked to receive updates from the position
locListener = new LocationListener() {
public void onLocationChanged(Location location) {
SendActivity.send(location, usr);
}
public void onProviderDisabled(String provider){
//labelState.setText("Provider OFF");
}
public void onProviderEnabled(String provider){
//labelState.setText("Provider ON ");
}
public void onStatusChanged(String provider, int status, Bundle extras){
//Log.i("", "Provider Status: " + status);
}
};
Looper looper = null;
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener, looper);
}
}
One other question, would I add the looper here or in the class that actually sends the information to the database? It uses HTTP Post to send to a PHP program that adds the info to a MySQL database.
I would be tempted to try a different tactic here. Android has a class called AsynTask which is written to ease the burden on developers of offloading work to be done on a thread.
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
In terms of writing to the DB and sending data back to a server, I would look at using a Service, but remember that the only Service that doesn't natively run on the UI thread is the IntentService
You should consider using AsyncTask class for such operations, it's pretty easy to use and it provides a simple way of synchronizing with the UI thread. Here's a nice post about threading in Android, you can learn more about AsyncTask in the Android docs. Hope this helps.
You can't access the 'context' or any UI object from a custom thread. This is because these are made in the main UI thread and you can't access these objects from your thread.
Just as Martyn said, you need to create a AsyncTask or use Handlers to access the context/ui.
In your case, go for the AsyncTask

Categories