I have two buttons -start and stop service buttons- in the fragment. In the initial state start button is enabled and stop button is disabled. When i click "start button",buttons states are changed. -It means start button is disabled and stop button is enabled. In the service i check gps state. If the gps is disabled, i call stopself method to destroy service. After calling stopself method, I wanna change buttons states in the fragment. But i didn't find any solution. How can i do this?
You can use below option.
In your fragment.
//In your on Create method
IntentFilter updateState = new IntentFilter();
updateState.addAction("UPDATE_BUTTON_STATE");
registerReceiver(updateStatueReceiver, updateState);
private BroadcastReceiver updateStatueReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("UPDATE_BUTTON_STATE")) {
// Here you can update your button state
}
}
};
//unregister Receiver in on Destroy method
unregisterReceiver(updateStatueReceiver);
In your Service Class
You can send broadcast using this code
Intent broadCastIntent = new Intent();
broadCastIntent.setAction("UPDATE_BUTTON_STATE");
sendBroadcast(broadCastIntent);
Related
now i have a server class that i run on a thread from an activity(i.e servActivity).now when i am not interacting with my app in anyway possible (like i have removed it from recent apps etc) the thread should stop which currently is not stopping. So i researched and i found that i should use a bound service. now a bound service i will have to bind it to servActivity and when servActivity is destroyed i have to unbind and stop service but i dont want to do that. i want to stop service when i am not interacting with the app. i also found that maybe i have to extend application class but cannot find the solution to achieve this?Is it advisable to extend the application class?
i want to be able to create a service running on independent thread from a particular activity(ie servActivity) and then be able to interact with the service from any activity and service should be active (even if the activity in which i started the service i.e-servActivity is destroyed by going to previous activity etc) through button or whatever until i am not interacting with the app(i have a notification controller which also needs to be closed to stop the interaction)
i have a client class on one device whose object i create again and again if i have to make request but i want to make only one object for server class because it has a while(true) loop so it keeps running so i want to be able to interact with the server from all activities and stop it when i am not interacting with the application
i also found a way in which i can make an abstract class which extends activity and extend that derived class to all the other activities in my app.But how to i bind the service to all the other activities in the class so that i can interact with the service from all the other activities?And how would i know that if all activities and notification controller have been stopped and there is no interaction with user?something like this how to know our app has gone to background in android
If there is there any other method please suggest
Please help
thanks in advance
You can create a BroadcastReceiver in your Service Class to interact/start/close your Service from any Activity or even from any App.
Your Activities can broadcast custom Action Strings which can be picked up by any BroadcastReceivers (even ones set up in Services) and thereby invoking their onReceive() methods allow communication.
1) I suggest you don't bind your Service to any Activity and instead use Intent to initiate it in your Activity like this....
//In your Activity
Intent i = new Intent(this, /*MyServiceClassName.class*/);
startService(i);
Or else your Service may still be active until you unbind it.
2) Create a BroadcastReceiver in your Service Class to listen for certain Action Strings broadcasted by your Activities....
//In your Service
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(/*"Action String to stop Service"*/)){
stopSelf();
}else if(action.equals(/*"Action string to interact with Service"*/)){
//Do what you want
};
3) Now set what Action Strings the Broadcast Receiver will listen for and also register it in your Service onCreate() method....
//In your Service onCreate() method
IntentFilter filter = new IntentFilter();
filter.addAction(/*"Action String to stop Service"*/);
filter.addAction(/*"Action String to do something"*/);
registerReceiver(receiver, filter);
4) And also unregister your receiver when Service onDestroy() is invoked as housekeeping....
//Service onDestroy()
#Override
public void onDestroy(){
super.onDestroy();
unregisterReceiver(receiver);
}
5) Finally broadcasting Action Strings from your Activities through Intent....
//From any Activity
Intent intent = new Intent(/*"your custom Action String that should match
up with whats set up with the BroadcastReceiver in Service"*/);
sendBroadcast(intent);
6) So once the broadcast is sent your receiver should pick it up then its onReceive() method will be invoked. Therefore you now have a medium for your Activities and Service to communicate through and also the Service will persist even after you close your app until you stop it explicitly with....
//From any Activity
Intent i = new Intent(this, /*MyServiceClassName.class*/);
stopService(i);
7) Stop service when app is stopped....
//In all your activities
#Override
protected void onDestroy() {
Intent i = new Intent(this, /*MyServiceClassName.class*/);
stopService(i);
super.onDestroy();
}
8) First you'd need to put a killcode intent action String in your Service as demonstrated in points 2 and 3 then put this code in your app's Activity onPause() methods....
#Override
protected void onPause() {
PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent(/*"Action String to stop Service"*/), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
// set alarm to fire 10mins (1000*60*10) from now (SystemClock.elapsedRealtime())
manager.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*60*10, pintent );
super.onPause();
}
And this in your app's Activity onResume() methods....
#Override
protected void onResume() {
PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent(/*"Action String to stop Service"*/), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
manager.cancel(pintent);
super.onResume();
}
I have an alarm clock application I am making. I have one activity where the user sets the time for the alarm. This registers a broadcast receiver class I have made to receive a broadcast at the time of the alarm, using AlarmManager. I then start a new activity in the receivers onReceive(). When this second activity starts, the alarm clock sound is played in onStart(). How can I tell if my activity has been started by a receiver or if the user is just multitasking with the application? I don't want my sound to play when the user silences the alarm, presses the home button, and then renters the app (while still on the sound playing activity).
Just send an extra via the intent you use in your onReceive() method:
Intent intent = new Intent(this, NextActivity.class);
intent.putExtras("playSound", true);
in your "sound playing" activity, you have to play the sound in onCreate():
boolean playSound = getIntent().getBooleanExtra("playSound", false);
This will return false if the intent-extra "playSound" does not exist or is set to false, true if it is set to true.
onCreate() is only called once (when the activity starts), while onStart() gets called everytime a user reenters your activity (i.e. through recent apps). You can see this in the lifecycle:
(diagram source)
Where Paused is called when something draws over you activity (e.g. low battery dialog), Stopped is called if you "exit" your app (e.g. through the home-button).
Start an activity or a service, etc., based on a received broadcast then you need a standalone broadcast receiver and you put that in your android manifest file. If you want your activity itself to respond to broadcasts then you create an instance of a broadcast receiver in your activity and register it there.
public class BRActivity extends Activity {
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
..................
..................
}
};
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_ACTION);
this.registerReceiver(this.broadcastReceiver , filter);
}
public void onPause() {
super.onPause();
this.unregisterReceiver(this.broadcastReceiver );
}
}
So, this way the receiver is instantiated when the class is created (could also do in onCreate). Then in the onResume/onPause I handle registering and unregistering the receiver. Then in the reciever's onReceive method I do whatever is necessary to make the activity react the way I want to when it receives the broadcast.
You can do as below:
For each alarm user sets, you put an boolean flag in sharedpreference to true. E.g. you have three alarms then in sharedpreference you will have 3 flags.
Now suppose a alarm broadcast is received for alarm1 and activity2 is started.
Now in activity2 first thing you check is whether the flag for alarm1 which you set in sharedpreference is true or false, if true play sound.
When user silences the alarm or press home button then you can mark this flag to false, so next time if user starts activity from background, flag in sharedpreference will be false and sound will not be played.
Same thing you can achieve using sqlite db, by setting flags in sqlite db table instead of sharedpreference.
For the intent used to launch the sound playing activity use the FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS flag. So if the user moves out of the activity, it cannot be resumed.
Intent intent = new Intent(context, SoundActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
or in manifest
<activity
android:name="SoundActivity"
android:excludeFromRecents="true" >
</activity>
There are couple of solutions:
(1) one approach is to use a Singleton Class which can be shared across activity.
In this approach set a boolean flag of Singleton class in BroadcastReceiver and then check that flag in the activity (which is fired from your BroadcastReceiver) where you play sound. Please reset the flag if it is set. This solution assumes that the Broadcast receiver is part of your Android App package.
(2)
Alternatively, you can also use Intet.putExtra ("Key", Value) method when you start an activity from BroadcastReceiver. You can check this key in the Activity you started from BroadcastReceiver to know who started this activity.
So this will take care of detecting where you come from.
If you are simply trying to set single (one-shot ) alarm then creating another activity for playing the sound is OK. If you set repeat alarm ( alarm plays at a multiple interval), I am not sure how your application will behave.
I prefer to play the sound in the Broadcast receiver itself (registered as remote receiver in manifest) for a specified duration for a given alarm ( like 30 sec of sound or you can ask user to configure it).
So this way you can use the same BroadcastReceiver for playing sound for single-shot & multi-repeat alarm.
I will use the same PendingIntent for setting both Single-shot and multi-repeat alarm.
You can simply set flag or any value in Intent that will determine what's your purpose in that class ..
For Ex: For playing sound set a Boolean value to TRUE in Intent and send same over that class using bundle ..
Else
Set that Boolean value to FALSE if starting alarm class from some other class.
This is the code to find if app is started via broadcast receiver.
public class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String AlarmTriggerString = (String)intent.getSerializableExtra("AlarmTrigger");
Intent i = new Intent();
i.setClassName("com.prasath.viki.bot","com.prasath.viki.bot.MainActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT|Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("FromBroacastReceiver",true);
i.putExtra("AlarmTrigger",AlarmTriggerString);
context.startActivity(i);
}
}
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boolean FromReceiver = (boolean)getIntent().getSerializableExtra("FromBroacastReceiver");
String AlarmTriggerString = (String) getIntent().getSerializableExtra("AlarmTrigger");
if(AlarmTriggerString != null && FromReceiver != null && FromReceiver == true)
{
// do something
}
}
I created a BroadcastReceiver and it runs only when my app shown in recent apps menu. If I remove my app from the recent apps the BroadcastReceiver will stop working.
How can I keep the BroadcastReceiver in background?
I register the BroadcastReceiver from my main activity (in OnCreate()).
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, intentFilter);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
This is not how you should register a receiver. You receiver stops working, because you construct it in onCreate, which means it will live as long as your app is alive. When the app gets destroyed, you also lose the the receiver.
If you register receiver inside an activity, you should always register it in onResume and deregister onPause, which will make it available while the activity is visible to the user. This is a use case when you want to have an active receiver while user interacts with an activity.
If you want a background receiver, you need to register it inside the AndroidManifest (with intent filter), add an IntentService and start it when you receive a broadcast in the receiver.
Here is a tutorial, you are interested in chapter 3.
If you need to be always on, start a foreground service. There is function in Service that lets you: startForeground. Then register your receiver when service is created and deregister when it's destroyed. Foreground services are quite nasty though.
Use a service with it.
Services can survive when the app dies if they have the right flag example:
public class MyService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY; //this defines this service to stay alive
}
#Override
public void onCreate() {
super.onCreate();
appStatus = APPISUP;
//This is a thread that stays alive for as long as you need
new CheckActivityStatus().execute();
//Not needed but in case you wish to lauch other apps from it
}
private class CheckActivityStatus extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
while(true) {
... //add something that breaks eventually
}
}
}
To lauch the service you have to lauch it from an activity like so:
Intent service = new Intent(getBaseContext(), MyService.class);
startService(service);
With the service the BroadcastReceiver still functions receiving whatever you want.
Note that the service sometimes stops and comes back. I haven't found out why but I'm betting on priorities of other apps that may ask the system to halt the service
I have two applications. One is a receiver and its starting my application. It works fine. Now i want destroy my application from the receiver itself. Is that possible ? Please note that these are my own application
It is possible but the activity has to finish itself using the finish()-method.
You can register an activity to a receiver using registerReceiver(..) and handle your logic in your activity. Don't forget to unregisterReceiver(...) inside the OnDestroy.
Example:
BroadcastReceiver mReceiver;
#Overrride
public void onCreate(Bundle savedInstanceState){
IntentFilter filter = new IntentFilter();
filter.addAction(...);
mReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// implement logic
finish();
}
}
registerReceiver(mReceiver, filter);
}
you cant directly control the lifecycle of one activity from another actvity
alternates to this could be :
you can set a timer in the new activity, if you want to end it after a certain amount of time, and call finish()' inrun()`
you can finish() the new activity on some events with EventListeners
I am trying to make my UpdateService for my digital clock widget stop when the screen is turned off to conserve battery, and then back on when the screen is activated. I currently have it in my onReceive() in my AppWidgetProvider, but I have also tried it in a BroadcastReciever.
My current code is:
public static boolean wasScreenOn = true;
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.d("Screen switched on. ", "Starting DigiClock UpdateService.");
context.startService(new Intent(UpdateService2by2.ACTION_UPDATE));
wasScreenOn = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.d("Screen switched off. ", "Stopping DigiClock UpdateService.");
context.stopService(new Intent(context, UpdateService2by2.class));
wasScreenOn = true;
}
Can anyone help me out here? I am stumped.
I'm fairly sure that you have to register your receiver in code for ACTION_SCREEN_OFF/ON. I don't think registering them in the manifest will work.
It seems you cannot register for the ACTION_SCREEN_ON/OFF intents with a filter in the manifest. You have to register your BroadcastReceiver in code. See here for an examples for an activity and a service.
You'll only receive the intent if your service or activity is running. In contrast to other broadcast events, the system will not start your process to handle the SCREEN_ON intent. It is similar to ACTION_BATTERY_CHANGED in this regard.
To handle this intent with a widget, I think you have to start a service that listens for the intent and then notifies your widget.
The article linked from Jens' answer to this same question provides a great presentation on this topic. I used it to implement a solution that worked for me.
The key insight is that your BroadcastReceiver can only be registered in code; you neither want nor need an entry in your manifest.
I recommend the article, but for those in a hurry, the simplest possible functioning approach would be to just paste something like this into your activity's onCreate() method:
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver screenoffReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.v("screenoffReceiver", "SCREEN OFF");
}
else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.v("screenoffReceiver", "SCREEN ON");
}
return;
}
};
registerReceiver(screenoffReceiver, filter);
As the article points out, for a running activity, onPause() / onResume() are always called when the power button is used to blank/unblank the display, so if you have something that you don't mind doing even in those cases for which the power button was not the reason for the onPause() or onResume() call, you can do it in those methods and thereby catch every instance of the power button being used to blank or unblank the screen (along with calls due to other causes), without the overhead of creating a BroadcastReceiver.
That was the case for me; I had a button that made my activity's main view invisible when pressed and visible when released, and if the user held the button down and then tapped the power button while the app was hidden, it would stay hidden permanently when the screen was unblanked by another tap of the power button. So in my case I only had to put a setVisibility(VISIBLE) call for my main view in my activity's onResume() override.
In fact, as the article shows, even if you only want to respond to the power button events, the proper way to do that is to set a flag in the BroadcastReceiver and then test that flag in onPause() and/or onResume() to see if the power button was the specific cause of the call to those methods.
Maybe you should use
public class MyReceiver extends BroadcastReceiver {..}
And then use this classname in the manifest