Service when activity destroy call again onStart - android

I have a android Service, in the onStart method i get many Strings from the Intent activity, and then execute a AsynTask to download files from internet.
When the activity is running this works ok, but when i stop the activity, this relaunch the onStart method, but obiusly the intent is null causing me nullPointerException.
What can i do the service dont entry on onStart, and continues the first asyntask to download all the files?
This is my code
#Override
public void onStart(Intent intent, int startId) {
desde = intent.getIntExtra("desde", 0);
hasta = intent.getIntExtra("hasta", 1);
email = intent.getStringExtra("email");
password = intent.getStringExtra("password");
new DescargaFotos().execute();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
and in Inicio.java (The UI activity)
Intent iService = new Intent(contexto,
ServiceDownloader.class);
iService.putExtra("desde", 0);
iService.putExtra("hasta", 5);
iService.putExtra("email", email);
iService.putExtra("password", password);
startService(iService);
EDIT:
New question:
I am using IntentService and i bind the service like this:
Intent iService = new Intent(contexto,
ServiceDownloader.class);
ServiceConnection serviceConector = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
Log.i("INFO", "Service bound ");
}
#Override
public void onServiceConnected(ComponentName name,
IBinder service) {
Log.i("INFO", "Service Unbound ");
}
};
iService.putExtra("desde", 0);
iService.putExtra("hasta", 50);
iService.putExtra("email", email);
iService.putExtra("password", password);
startService(iService);
bindService(iService, serviceConector,
Context.BIND_AUTO_CREATE);
And now my problem is, in my galaxy nexus, if i enter in app runtime list, and destroy my app, the service stopped, and stop donwload, stop send notification etc? How must i bind the service to solve this?

Use an IntentService. IntentService is specifically designed to do what you want. You don't have to implement onStart, onStartCommand, etc. The work runs on a background thread. Once the work finishes, the Thread is destroyed.
IntentService will continue to run regardless of the state of the Activity.
One problem you may have is that you're sending out your Intent in the wrong place in your Activity, or you're not checking to see if the operation is complete. Before you send the Intent, check a flag in SharedPreferences (if the flag doesn't exist, it means you're starting for the first time). When you send the Intent, store a flag in SharedPreferences to indicate that you sent it. When your IntentService receives the Intent, have it update the flag to say it received it. Before the IntentService finishes, have it update the flag again. And so forth.

I do not have reputation to comment your question, so I will write a answer :)
First off all, in my opinion, if your Service do just this, get some string and download files from the Internet, you do not need the service. The AsyncTaks is enough to solve your problem and it is more simple to implement. Doing that, you avoid the problem with your intent.
From Android API:
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.
However, if you decide to continue using a service, lt me know exactly when startService is called in your activity.
If you have some doubt about when use AsyncTask, Service, IntentService and Thread, this link can help you.

This would be my suggestion...
Use a thread in the service rather then AsyncTask since AsynTask should only be used small task. Check following statement from AsyncTask javadoc:
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and
FutureTask.
So from your on start check the status of your thread, if it is running then don't do anything, if it is not running then start the thread that would download your images...

Related

How do I run parallel actions in android?

How do I run a parallel action (process) to the main app in Android?
I know that, there are a lot of ways to do it: Threads, Tasks, Handlers and etc'...
This is the way I chose. But I think it takes a lot of memory and doesn't closes in the interrupt call.
checkReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO: Check is this a good way to handle threads
Thread t = new Thread() {
#Override
public void run() {
internetConnectionManager.TryConnect();
this.interrupt();
}
};
t.start();
}
}
};
Two things wrong with your arroach:
You should not start a thread in onRecieve method. The reason is explained here :
This has important repercussions to what you can do in an
onReceive(Context, Intent) implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes
Second, calling Thread.currentThread().interrupt() does not make any sense in your example since your thread is already done by that line and will finish, and also because you don not check interrupted flag anyway.
The better way, in my opinion, would be to start a simple IntentService from your onReceive code. Here is a simple tutorial.
Important edit based on FunkTheMonk's comment:
If the broadcast comes from an alarm or external event, it is possible that your device will go to sleep shortly after onReceive returns (even if you create a service). If that is the case, instead of using regular BroadCastReceiver you should extend WakefulBroadcastReceiver from support library.
Use handler
if you want to stop handler then fire an intent with some value eg.("quit handler")to receiver
and call remove call back and inside handler you can handle the rest using ACTION switch
you can also use intentservice

Uploading Image and displaying outcome on UI: AsyncTask or Service?

My Android application has to:
upload an image to the server
make 3 ( quick ) calls to a REST web service using the uploaded image image
get output from webservice
display output on ui.
I'm confused about whether I should use a Service or AsyncTask.
I think I should use an AsyncTask because the tasks need to be done in the background and the outcome needs to be displayed on the UI once the process is complete. The doInBackground() and postExecute() methods seem perfect for this sort of thing.
However, I've read from the Android Documentation and several StackOverflow answers that using Services is more appropriate. The problem is that I want to display the output on the UI as soon as the task is complete. If the user quits the app, then I want the upload to stop.
I'm confused: Is AsyncTask really the better choice?
You should create an IntentService. Send an intent to the service to start it. Send back an intent with the result using a LocalBroadcastManager (from the support library). The IntentService stops itself when it completes, unlike regular Services.
If the user rotates the device while the AsyncTask is executing the result will be lost since the AsyncTask thread is associated with the activity that was destroyed by the rotation. You can find an example here on StackOverflow of how to circumvent this problem, but it's much more code and more complex than writing an IntentService. Since the IntentService is on its own thread, it doesn't get lost when the activity is destroyed.
public class MyIntentService extends IntentService {
public static final String SERVICE_NAME ="whatever";
public MyIntentService() {
super("MyIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Get input from the intent, do your http stuff here,
// create a new intent to send back
LocalBroadcastManager.getInstance(this).sendBroadcast(intentToSendBack);
}
}
Check out the IntentService docs: Intent Service is about 1/3 down the page
Use a LocalBroadcastManager in your activity to listen for the returning intents. You just hook it up in the OnResume event handler and unhook it in the OnPause handler. So after your original activity is destroyed on the rotation, the new one will start listening. The magic of LocalBroadcastManager queues up the intent for that small period of time between the destruction of the first activity and the creation of the second.
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(MyIntentService.SERVICE_NAME);
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, filter);
}
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}
private BroadcastReceiver onNotice = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do your UI stuff here....
}
}
There is more detail on LocalBroadcastManager in the docs. There are some other good side effects of LocalBroadcastManager. Intents sent this way do not leave the application scope, so other apps can't snoop on data you pass around, and your activity processes the result without being forced into the foreground.
Don't forget to register the service in your AndroidManifest.xml.
IF you are doing network related stuff in your app you need to use an AsyncTask no matter what you do because you will get a NetowrkOnMainThreadException. you are not allowed to do anything network related on the UI thread. Since a service runs on the UI thread you will still need an AsyncTask in the service.
So if it were me I would not worry about the service if you need to update the UI when its done

start service from activity and wait until its ready

I want to start a Service from an Activity.
First I tried it with a LocalBinder. This works, but the service was bound to the activity. I don't want to stop the service when the activity is gone. I found no solution with the LocalBinder so I removed it and tried this:
use a singleton instance in the service
call the startService methode in a new thread and waits until the instance is available:
final Intent recordService = new Intent(RecordActivity.this, RecordService.class);
Runnable r = new Runnable() {
#Override
public void run() {
startService(recordService);
}
};
new Thread(r).start();
Log.i(MMLF.T, "service instance: "+serviceInstance);
final ProgressDialog mProgressDialog = ProgressDialog.show(
RecordActivity.this, "Waiting", "wait until record service is loaded",
true);
while (serviceInstance == null) {
serviceInstance = RecordService.get();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(MMLF.T, "could not sleep", e);
}
}
mProgressDialog.dismiss();
But this doesn't work, too. It stucked in the waiting loop. If I remove this waiting stuff and the new new Thread(r).start() line is the last, the activity and service start fine.
How to start a service independent from an activity? I also let them to communicate with each other. The activity should call two methods (start and stop recording) and the service should send messages. For the second I can use LocalBroadcast.
Your question is a little confusing, because Services already live independently of Activities. Note, however, that Services run in the main thread by default. If you want to run the Service in a different thread (and in this case it looks like you do), you will have to set up a Messenger object and send messages between your worker thread and your UI thread. You can also look into using AIDL (on top of which Messenger is really built anyway). Your communication, if you don't use a Messenger, could use intents. If this is the case, you should look into IntentService. However, this only works when you are sending messages to the Service, not back and forth. If you want back and forth communication, you will have to use some sort of Messenger or similar pattern.
By the way, using an IntentService for things like 'stop' and 'start' is pretty common. Typically there is also a background thread, which communicates with the Service using a Messenger or something similar, and then sends / receives messages to instruct the worker thread as to what should be done.
You might also look into AsyncTask, as it makes this kind of thing much simpler.

How to start long running background task in android service

Having read most of the available documentation on Android services on the developer site and here in stackoverflow, I'm still confused by several aspects of running a service in a separate task. Hopefully someone can put me on the right track.
Let's say we have trival service framework such as
public class HliService extends Service {
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
}
}
and in the manifest, I have
<service android:name=".HliService" android:process=":HLI_Comms"/>
so that the service runs in its own thread.
The intent of the service is to provide a background task that will communicate
to a device using a TCP socket and do some other stuff. At the risk of ignoring battery issues etc, basically I'd like it to run forever.
Something like
// Method that communicates using a TCP socket, and needs to send
// information back to the activity and receive messages from activity
// not shown here.
private void dummytask() {
boolean keepGoing = true;
while (keepGoing) {
// do useful stuff in here
// sets keepGoing false at some point
}
stopSelf();
}
What is the best way to initiate this method/task ?
I have looked at code in the developer site that uses a message handler and a looper, which I only partly understand, but it seems very complicated and perhaps more than I require?
I don't believe I can call this method from either onCreate() or onStartCommand() since then neither would complete when invoked from the system ? Should I start it with a timer or alarm?
I will need to add a message handler to communicate with the the gui activity, but since I'm starting the service in another thread (by virtue of the manifest "process" instruction), do I need to use AIDL instead?
I have also looked at using AysnchTask rather than extending Service, but it seems better suited to running a task and then terminating.
so that the service run in its own thread.
That puts the service in its own process. This is generally something to be avoided, as it consumes extra RAM and CPU (for IPC). You can create a thread just by creating a Thread or any number of other means, most of which have been in Java for a decade or so.
At the risk of ignoring battery issues etc, basically I'd like it to run forever.
It is pretty much impossible for a service to run forever. Users or the OS will get rid of your service eventually.
What is the best way to initiate this method/task ?
Call dummytask() from a background thread.
do I need to use AIDL instead?
No. Your service can broadcast an Intent, or invoke a PendingIntent supplied by the activity, or send a Message via a Messenger supplied by the activity, etc. The best would be to use the LocalBroadcastManager from the Android Support package, but that will not work across process boundaries, forcing you into more expensive communications options.
I think you could use a IntentService which you run by setting up a (regular) alarm (AlarmManager.setRepeating) with a PendingIntent in it. You can notify the UI by broadcasting an Intent from the IntentService and receiving it in your UI through a BroadcastReceiver.

Android : Do Application Login in background on boot-up

I have a VOIP Application, I need to login the application in background on device bootup.
Currently the init to my application is done on UI Active(onCreate()).
I have the following things in my mind, can anyone help and clear my doubts.
The service design is must to achieve this task??
Which Service Remote(AIDL) or Local Service and why?
How does the UI and Service interaction happens?
After UI is active who gets the Call- Backs? UI or Service?
Should i make Service as my Controller i.e Service to UI data Pass Vice-versa?
Sample App: Skype.
So there are many ways to achieve what you want, it is a matter of what fits your style and design better. Hopefully you will find this information useful.
For the application to login in the background on startup there are a few option. The first thing you will need is a BroadcastReceiver which is defined as a receiver in the manifest. Have the BroadcastReceiver catch the ACTION_BOOT_COMPLETED intent. From here you can launch your Service. This leads to #2.
If all you are doing are RESTful calls then really an IntentService would be ideal. The difference between an IntentService and a Service is simple: An IntentService runs off of the main thread, executes it's 'code' and dies. A Service, however runs on the main thread (this is an important fact) and is long running so it has to be told to stopSelf(). To take matters further, a Service is also less likely to be killed compared to an Activity (application components are killed to make room in memory for newly launched apps), ie. it takes higher precedence. The service can also be declared a foreground service which requires a notification but give even higher precedence. I think in your case a Service would be perfect.
Once your UI (Activity) is opened the best way to connect to the Service would be the Binder. This will allow multiple interfaces to the Service from different applications / components if need be. AIDL is pretty cool stuff but from my experience much harder to manage since all parameters must be primitive or Parcables. AIDL is also slower an less efficient because it is really a form of IPC. When a Service is started with an intent the onStartCommand() method is called. If the service is started by an application trying to bind to it then the onBind() method is called. But you can start the Service with and Intent and then bind to it. If you prefer the RESTful approach where you just have quick calls for data you can use an IntentService with a ResultReceiver. This is a great article written about Google I/O examples and just overall well implemented if you are interested in the IntentService and ResultReceiver.
This is up to you. Using the Binder or AIDL your Activity can call the Service methods just like object method where the 'callback' would just be the method return. If you use a ResultReceiver the Activity interfacing the Receiver would be the callback. You could also just pass Intents back and forth but this could get messy. Again for your case the Binder approach would be good as well as a Receiver.
Think of the Service as a model in the MVVM system - use it as a helper to get data from, not as something that controls the logic of the application.
Sorry if this seems messy there are so many ways to achieve what you are looking for. Its just a matter of what fits your situation best what you 'feel' is better. Not to mention the Android SDK is pretty large. I tried to hit on all the topics that could help you out. Good luck!
Try a service with a boot reciever. Here is an example I found after a quick google search. Then make sure to store in the login info somewhere for when the app starts. Not sure what callbacks you might have, so really hard to answer that part. I would say that if the callbacks should affect the UI then let the activity take them over when it starts up. If you need a UI when only the service is running, probably best to throw up a notification and have it call the appropriate activity with the callback data.
you can authanticate user login by background services
package com.javaorigin.android.sample.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
String tag="TestService";
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show();
Log.i(tag, "Service created...");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(tag, "Service started...");
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class SampleAction extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView view = new TextView(this);
view.setText("Service Test");
Intent i = new Intent();
i.setClassName( "com.javaorigin.android.sample.service",
"com.javaorigin.android.sample.service.MyService" );
bindService( i, null, Context.BIND_AUTO_CREATE);
this.startService(i);
setContentView(view);
}
}
If you login is takes so long use [AccountManager][1] and do it only once.
The idea behind the AccountManager a token or whatever credentials you need to use in your Service.
In your particular case I think the best way of communicating your Activity with the Service is binding to it.
Best source of knowledge about basic Service usage is SDK. Long story short AIDL is used for IPC communications and as long as you run the service in the same process you don't need it. I suppose you have two options:
If the only thing you need is just login, you can start a service on boot up, login and then i.e. send a sticky broadcast with bundled login data which will be then received in application. See this question for a good set of ways to start a service on boot up.
#Override
public void onCreate() {
Data data = performLogin();
Intent i = new Intent(ACTION_VOIP_LOGIN);
i.putExtra(EXTRA_LOGIN_DATA, data);
mContext.sendStickyBroadcast(i);
}
...
private final class LoginReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// You may use a Bundle instead
Data data = intent.getParcelableExtra();
processLoginData(data)
}
}
protected void onCreate(Bundle savedInstanceState) {
...
IntentFilter filter = new IntentFilter(ACTION_VOIP_LOGIN);
mContext.registerReceiver(new LoginReceiver(), filter);
}
In second case you might want to move all your logic to the service. Here you'll extend the Binder class. See this SDK article for details.

Categories

Resources