How can I call a method while my application is closed on Android?
I've tried:
Onpause(), OnDestroy(), and OnStop(). With no luck.
What I want is receiving something from the database and do my reaction
based upon when the application is closed.
I think you can use broadcast or service to do it.
You could create a base activity (BaseActivity class) from which all your activities would have to be derived. Then inside BaseActivity.onCreate - you would increase some SharedPreferences counter, and inside BaseActivity.onDestroy you would decrease it. Now when that counter is equal to zero, you might assume your application is closed - but the process might still run in the background.
What I want is receiving something from the database
now I assume you already know how to "receive something from database". This could be background Service, where you could check SharedPreferences and do your processing.
What is the trigger?
Part 1 : Intent -
By example, you can set an alarm, that launch an Intent.
Part 2 : Broadcast Receiver - You must create a Broadcast Receiver (which reacts to an intent).
Part 3 : Service - The Broadcast Intent will launch a service that will execute when the application is not open.
Related
I would like to have your opinion.
I have got an Activity A with a button (and a listener of course). It starts a Service and a Notification.
I would like that when I click on the notification, it runs a new Activity B and it stops the Service.
My problem is : how use an Indent to send the datas from the Service to the Activity B when the Service is stop? (I need the very last values of datas in my Service)
Thanks in advance for yours answers.
Intent has a couple of methods called putExtra(String name, ...) which allow you to put a number of EXTRAS on the intent. You don't specify a whole lot of detail in your question. This is the most generic answer I can give you.
Before calling stopSelf() on the service you should start the Activity B with the intent (say I). Immediately after calling startActivity(B, I), you should call stopSelf on service.
While creating I, you can put data into the intent as EXTRAs.
I don't know if this is possible, but I would like to do the next:
Imagine an app with 2 activities: MenuActivity and OtherPurposeActivity.
So, on the onCreate method of Menu I had run the Service. In the same Activity (Menu), I can easily "connect"(Edit: communicate) with this Service with no problems.
Then, I click the only button there is on MenuActivity, which starts OtherPurposeActivity. Here comes the question:
How can I connect to the Service I had run on MenuActivity? Is it possible? (I hadn't called stopService).
Thanks in advance.
Edit: Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
/* Execute service */
Log.d("SERVICE", "Launching service");
Intent msgIntent = new Intent(MenuActivity.this, ServerProcessingService.class);
msgIntent.setAction(ServerProcessingService.ACTION_STATUS);
startService(msgIntent);
/* Connection to the IntentService */
IntentFilter filter = new IntentFilter();
filter.addAction(ServerProcessingService.ACTION_STATUS);
//filter.addAction(ServerProcessingService.ACTION_CONTROL);
rcv = new ProgressReceiver();
registerReceiver(rcv, filter);
}
So I can handle the communication with the ProgressReceiver class. But, what if I open another activity, and this service still running? Can I access to it?
How can I connect to the Service I had run on MenuActivity?
Another activity that wants to communicate with the service can use exactly the same method as MenuActivity. startService() will only start the service if it is not already running, and then send the intent to onStartCommand() in all cases, so it is all right to call start service from multiple activities.
As a commenter pointed out, if your activity requires ongoing communication with a service, you should bind to it.
Is it possible? (I hadn't called stopService).
An IntentService will stop itself if it has no work to do, so it doesn't matter that you did not stop it explicitly. If the service needs to continue running, don't use an intent service.
To be on the same page I will describe briefly how I understood your dilemma.
You have an IntentService perfroming some operation which provides at the end some results. You are starting this process in one activity(asynchronously of course) and switch immediately to another one. Now, you are not sure whether service will finish the work before you switch to second Activity and result will be lost.
Basically, approach with BroadcastReceiver would be a good choice but if you won't register on time the data will be lost and service will end it's work. You could let the service to store the result before it ends, in DB, file or even in memory(depending on data type). When your second Activity start you can check if there is data waiting for you, if not you can wait for BroadcastReceiver to deliver it.
You could also use Otto library which is far more advanced solution than BroadcastReceiver. It allows to return to registered observer(Activity) the last result and what is more important it will allow your service to check if any observer received the message. If not you could only then store last result.
I was playing around with services and dialogs, and I got a doubt. Within a dialog, I am starting a service like this:
Intent lock = new Intent(getActivity(),AppLockService.class);
getActivity().stopService(lock);
getActivity().startService(lock);
Now the first time I call the dialog through
dialog_name.show(getFragmentManager(), "dropbox");
Upon pressing the OK button, the intent is launched. Now later, during the same app execution, the dialog is triggered again ( which is according to my code logic -- nothing wrong here). The code in the dialog then stops the previously triggered intent and starts the new intent.
My question is this:
lock is a local intent variable as per my definition. So how does it know that it has to stop that particular service I have triggered here the first time? Would someone please explain this to me?
You don't have to keep track of the service in a variable because Android does it for you.
The way that the OS treats a service is that it will not allow more than one instance of the service be to running at any time.
So at any moment there are 0 or 1 instances of your service. If there are 0, no problem, the OS will ignore the call to StopService. If there is 1 instance, it must be the instance you started previously - so it will be stop that one.
I have managed to get an Activity to start from my onReceive() methdod, but I really need to do a startActivityForResult();.
Is there any way I could do this?
On a side note, how would I make my app become a 'camera' app, as in it would appear when an app started the intent to take a picture?
The important thing to know about broadcast receivers is that you should not add long running processes in it, because after something like 5 seconds your app will crash.
The best thing to do in your case is to intent to other Activity from your broadcast receiver, and from that activity use startActivityForResult(), get the picture and continue from there...
startActivityForResult can only be called from an Activity since it is defined in the Activity class and require instance of activity.
You can only call startAcivity() from broadcast receiver since in onRecieve() you only have access to generic context object and it does not have startActivityForResult method defined in the class..
I currently have a Service in Android that is a sample VOIP client so it listens out for SIP messages and if it recieves one it starts up an Activity screen with UI components.
Then the following SIP messages determine what the Activity is to display on the screen.
For example if its an incoming call it will display Answer or Reject or an outgoing call it will show a dialling screen.
At the minute I use Intents to let the Activity know what state it should display.
An example is as follows:
Intent i = new Intent();
i.setAction(SIPEngine.SIP_TRYING_INTENT);
i.putExtra("com.net.INCOMING", true);
sendBroadcast(i);
Intent x = new Intent();
x.setAction(CallManager.SIP_INCOMING_CALL_INTENT);
sendBroadcast(x);
Log.d("INTENT SENT", "INTENT SENT INCOMING CALL AFTER PROCESSINVITE");
So the activity will have a broadcast reciever registered for these intents and will switch its state according to the last intent it received.
Sample code as follows:
SipCallListener = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(SIPEngine.SIP_RINGING_INTENT.equals(action)){
Log.d("cda ", "Got RINGING action SIPENGINE");
ringingSetup();
}
if(CallManager.SIP_INCOMING_CALL_INTENT.equals(action)){
Log.d("cda ", "Got PHONE RINGING action");
incomingCallSetup();
}
}
};
IntentFilter filter = new IntentFilter(CallManager.SIP_INCOMING_CALL_INTENT);
filter.addAction(CallManager.SIP_RINGING_CALL_INTENT);
registerReceiver(SipCallListener, filter);
This works however it seems like it is not very efficient, the Intents will get broadcast system wide and Intents having to fire for different states seems like it could become inefficient the more I have to include as well as adding complexity.
So I was wondering if there is a different more efficient and cleaner way to do this?
Is there a way to keep Intents broadcasting only inside an application?
Would callbacks be a better idea? If so why and in what way should they be implemented?
UPDATE 2015:
This question/answer still gets a little bit of activity, but it is over 5 yrs old and things have changed quite a bit. 5 years ago, the answer below was how I would have handled it. Later I wrote a very lightweight dependency injection solution that I was using for a while (which I mentioned in the comments). Nowadays, I would answer this question using Dagger and RxAndroid. Dagger to inject a "mediator" class into both the Service and all Activities that need to be notified, the Service would push the status update to the mediator class, and the mediator class would expose an observable for the activities to consume the status update (in place of the OP's broadcast receiver).
Original answer
I usually subclass Application and let my in-app communication go through this class (or have a mediator owned by the Application do the work...regardless, the Application being the entry point for the service to communicate with). I have a bound service that needs to update the UI as well (much simpler than yours, but the same idea) and it basically tells the app its new state and the app can then pass this information along in one way or another to the currently active activity. You can also maintain a pointer to the currently active activity (if there is more than one), and make decisions whether or not to simply update the current activity, broadcast the intent to launch a different activity, ignore the message, etc. I would also subclass Activity and have your new activity base class tell the Application that it is currently the active one in onResume and that it is being paused in onPause (for cases where your service is running in the background and the activities are all paused).
EDIT:
In response to the comment, here's more specifics.
Your application currently consists of Activity-derived and Service-derived classes for the most part. Inherently, you get functionality from an instance of the android.app.Application class. This is declared in your manifest (by default) with the following line:
<application android:icon="#drawable/icon" android:label="#string/app_name">
The application element in your manifest doesn't use the android:name attribute, so it just creates an instance of the default android.app.Application class to represent your global application context.
In my apps, I create a subclass of Application (ApplicationEx, for example) and I tell my app through the manifest that this is the class to instantiate as MY global application context. For example:
<application
android:name="com.mycompany.myapp.app.ApplicationEx"
android:icon="#drawable/app_icon"
android:label="#string/app_name">
I can now add methods to ApplicationEx for activities and services to use to communicate. There is always a single instance of your global application context, so this is your starting point if anything needs to be global for your app.
A second piece of this is that instead of deriving my services and activities from Service and Activity, I create a subclass of each with a getAppContext method that casts the return value of getApplicationContext (which exists already in both of these classes because they derive from Context) to my ApplicationEx class.
So........
All that being said, you add a CurrentActivity property to your ApplicationEx class of type Activity (or ActivityBase if you subclass it as I do). In ActivityBase's onResume method, you pass yourself to ApplicationEx for it to set CurrentActivity to that activity. Now, you can expose methods on ApplicationEx to pass information directly to the current activity instead of relying on the Intent mechanisms.
That's about as clear as I can make it
You can send broadcast intents just to your own application and not system wide with LocalBroadcastManager:
Helper to register for and send broadcasts of Intents to local objects within your process. This is has a number of advantages over sending global broadcasts with sendBroadcast(Intent):
You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
It is more efficient than sending a global broadcast through the system.
However, I'd still recommend going with the Service approach and locally binding and talking through Handler when necessary to update UI components for efficiency.