I have problem with stopping a service from activity.
Declaration of my service:
public class MyService extends Service implements LocationListener { .. }
This service is called when the button is pressed:
public void startMyService(View view)
{
ComponentName comp = new ComponentName(getPackageName(), MyService.class.getName());
ComponentName service = startService(new Intent().setComponent(comp));
}
In another method (launched by button click) I want to stop it:
public void stopMyService(View view)
{
stopService(new Intent(this, MyService.class));
}
Unfortunately, it is not working. It seems to me that this service is replaced by another one. Furthermore, it´s cumulating - for example, when I start the service for the second time, there are two of them, running, etc. Could somebody help me? Thanks in advance for your help.
UPDATE : Android Manifest (only my service):
<service android:name=".MyService"
android:enabled="true"
android:exported="false"
android:label="LocationTrackingService"
/>
You could add a BroadcastReceiver to your service (or a static method - depending on your preferences) and call Context.stopService() or stopSelf(), e.g. add ...
public static String STOP_SERVICE = "com.company.SEND_STOP_SERVICE";
private final BroadcastReceiver stopReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(STOP_SERVICE)){
MyService.this.stopSelf();
}
}
};
... to your service (assuming it's called MyService). Then call registerReceiver(stopReceiver, STOP_SERVICE); in the onStartCommand() method and unregisterReceiver(stopReceiver); in onDestroy(). Finally send the broadcast from anywhere you need to stop the service:
Intent intent=new Intent();
intent.setAction(MyService.STOP_SERVICE);
sendBroadcast(intent);
If you have some threads you have to stop them before (probably you have and you started the service sticky, did you?)
Related
My app will not invoke the intentservice request from the wakefulbroadcastreceiver
Manifest:
<service
android:name=".MyWearableListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED"/>
<data android:scheme="wear" android:host="*"/>
</intent-filter>
</service>
<service
android:name=".CounterActivity$WearableReceiverService"
android:exported="false">
</service>
<receiver
android:name=".CounterActivity$WearableReceiver"
android:enabled="true">
</receiver>
So i register all receivers and services.
inside my main activity i have these as sub-classes within the main class so i can call the method in the main class msgReqAction()
public class WearableReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, WearableReceiverService.class);
startWakefulService(context, service);
}
}
public class WearableReceiverService extends IntentService {
public WearableReceiverService(){
super("WearableReceiverService");
}
#Override
protected void onHandleIntent(Intent intent) {
msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
WearableReceiver.completeWakefulIntent(intent);
}
}
I don't think having these as subclasses should hinder the situation but it may. if i must have these outside the main class for operation let me know.
finally i begin the whole process from a listener outside the main activity that listens for a message from the wearable
#Override
public void onMessageReceived(final MessageEvent messageEvent) {
nodeId = messageEvent.getSourceNodeId();
String incomingPath = messageEvent.getPath();
int incomingReq = Integer.parseInt(new String(messageEvent.getData()));
if(incomingPath.equalsIgnoreCase(MyConstants.MSG_COUNTER_REQ_PATH)) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(MyConstants.BROADCAST_ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(MyConstants.BROADCAST_DATA_REQ, incomingReq);
sendBroadcast(broadcastIntent);
}else if(incomingPath.equalsIgnoreCase(MyConstants.MSG_DEFAULT_PATH)){
}
}
public static final String BROADCAST_ACTION_RESP = "com.example.johnbravado.zionwork.MESSAGE_PROCESSED";
my project is com.example.johnbravado.zionwork - also on a side note is there a way to change and refactor that in android studio easily so i can get rid of example or change it completely?
when i run the debugger the system gets all the way to
startWakefulService(context, service);
then it crashes without entering the intent service. is there somethig simple i am missing amongst all this which is preventing it from going into the service and doing work. best i can tell is it does not go into the service at all. i added some intro lines of the service
#Override
protected void onHandleIntent(Intent intent) {
int data;
data = 0;
data++;
msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
WearableReceiver.completeWakefulIntent(intent);
}
and tried to run debug points on these lines and it didnt get there.
You cannot have a Service defined as a non-static inner class.
A non-static inner class contains a reference to its outer class. This means that in order to create a new instance of the inner class, you need to have an instance of the outer class.
When Android tries to start your Service, it tries to create a new instance of the inner class. This fails, because Android does not have an instance of the outer class to use in the creation.
The same rule applies to the BroadcastReceiver.
Solution: Move all your inner classes to full-fledged classes (in their own source files).
The solution was to eliminate the WakefulfulBroadcastReceiver and secondary IntentService. Instead, I used a BroadcastReceiever and sent a broadcast directly from the Wearable listener function and used that to process data directly within the activity.
public class WearableReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Intent service = new Intent(context, WearableReceiverService.class);
//startWakefulService(context, service);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado.zionwork");
wakeLock.acquire();
// Do Work
msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
wakeLock.release();
}
}
Even though i do not do much that would necessarily require a wakelock. if i decide later to do more work i have it ready to go. i am not sure if this is best place for the wakelock either never really used them but that is another topic.
I removed reference to the extra service and receiver in the manifest file also. works good now
I have an IntentService defined as below:
<service android:name=".service.AppService" android:process=":app_process" android:icon="#mipmap/ic_launcher" />
I have a WakefulBroadcastReceiver that receives some data and I would like to call my already running service above. The service above is always running, even if it is killed, it restarts. How can I pass messages to that?
I read the following:
http://www.mysamplecode.com/2011/10/android-intentservice-example-using.html
http://www.truiton.com/2014/09/android-service-broadcastreceiver-example/
http://developer.android.com/guide/components/services.html
I tried to do a startService, PendingIntent among other things and nothing seems to work.
First of all, remember that an IntentService works in a different worker thread, there for it's not possible to have intercommunication with the Activity that invoked it. That's why mostly we use them for synchronization on background where feedback to the user is not needed. However, if you want to pass some information to the Activity, you have to use a BroadcastReceiver as you said, and from there create the Intent that will send "data" to the Activity.
Going back to your question, you have to add the service and the receiver in your AndroidManifest.xml inside the <application> tag
<service android:name=".AppService"
android:enabled="true"/>
<receiver android:name=".WakefulBroadcastReceiver" >
</receiver>
Then in your Activity launch the service like this (whenever you need it, in the onCreate, or in a button listener)
IntentFilter filter = new IntentFilter(WakefulBroadcastReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
WakefulBroadcastReceiver broadcastReceiver = new WakefulBroadcastReceiver();
registerReceiver(broadcastReceiver, filter);
In your BroadcastReceiver you override the onReceive() method like this:
#Override
public void onReceive(Context context, Intent intent) {
// HERE IS WHERE YOU RECEIVE THE INFORMATION FROM THE INTENTSERVICE, FROM HERE YOU CAN START AN ACTIVITY OR WHATEVER YOU AIM
Toast.makeText(context, "IntentService Broadcasting", Toast.LENGTH_SHORT).show();
}
Also in the same BroadcastReceiver add this variable that identifies the intentfilter:
public static final String ACTION_RESP = "MY_FILTER_NAME"
In your IntentService class you have to override the onHandleIntent() method like this:
#Override
protected void onHandleIntent(Intent intent) {
String msg = intent.getStringExtra("MSG");
Intent broadcast = new Intent();
broadcast.setAction(WakefulBroadcastReceiver.ACTION_RESP);
broadcast.addCategory(Intent.CATEGORY_DEFAULT);
broadcast.putExtra("MSG", resultTxt);
// HERE IS WHERE YOU SEND THE INFORMATION YOU LOADED TO THE APP
sendBroadcast(broadcast);
}
I have a demo project in my GitHub account here, where I use bound and unbound services and IntentServices:
https://github.com/isaacurbina/PermissionsAndServices
I hope it helps.
Kind regards!
You can write this in your class that extends WakefulBroadcastReceiver :
#Override
public void onReceive(Context context, Intent intent) {
Intent gcmIntent = new Intent(context, MessageService.class);
gcmIntent.putExtras(intent.getExtras());
startWakefulService(context, gcmIntent);
setResultCode(Activity.RESULT_OK);
}
And write this in your class that extend IntentService :
#Override
protected void onHandleIntent(Intent intent) {
Bundle bundle = intent.getExtras();
//do sth with that data
MessageReceiver.completeWakefulIntent(intent);
}
the title says all, I need to change the variable of my service from a activity in my other app , what to finalize the service or not, this is possible?
I found the Message object , but I do not quite understand
The simplest solution would be to implement a BroadcastReceiver. Your Service listens for the Broadcast and the other App sends the Broadcast.
Example Reciever:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Get bundle from intent and use it to set your Variable in your Service
}
}
Example Broadcaster (courtesy of Vogella):
Intent intent = new Intent();
intent.setAction("de.vogella.android.mybroadcast");
sendBroadcast(intent);
In my Android project, I have a normal Service:
public class MyService extends Service{
#Override
public int onStartCommand(...){...}
...
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MyApp","MyService onDestroy() is called!");
}
}
In my BroadcastReceiver class, I stop MyService & do another task :
public static class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.stopService(new Intent(context, MyService.class));
doAnotherTask();
}
}
According to my log, onDestroy() of MyService is executed after doAnotherTask() is done.
How can I guarantee that onDestory() of MyService is executed before doAnotherTask() get called?
P.S.: I thought I could do something like:
boolean isStopped = context.stopService(new Intent(context, MyService.class));
if(isStopped){
doAnotherTask();
}
But it could be possible that there is no service has been started, which means stopService(...) does nothing. So, I can't rely on my above code.
call startActivityForResult() .... and after you got the onActivityResult,.... call your method doAnotherTask()
i think that will do the job
How about sending a special intent to your broadcast receiver from the onDestroy() function? When your receiver gets it, then call doAnotherTask(). (I am assuming that you can't simply call doAnotherTask() from onDestroy() directly.)
send a broadcast in the service's onDestroy function and in it's observer do your after things
The call to stopService() is asynchronous. You are basically telling Android that you want it to stop the Service. You have no control over when this actually occurs.
If you need to trigger something AFTER the Service is destroyed, then you send a broadcast Intent in MyService.onDestroy() and use that to trigger whatever you want to happen when the Service is destroyed.
I've a local service that is started in my main activity. The service is responsible for network I/O. It also interacts with other activities in my application. Till, now the service was only "providing" data to activity (using callbacks and not Intents.)
Now I need to send data (custom objects) from my activities to the service. I understand one way to do it using Intents. I know it is possible to receive an Intent in the service by overriding the onStartCommand() in my service. But it's not clear to me if the onStartCommand will be invoked every time I broadcast an Intent from my sending activity. Can a Service also be BroadcastReceiver ? If yes - how ?
Thanks.
You can create a BroadcastReceiver object in the service and register it to listen to any broadcast event you want. It's something like this:
BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//handle the broadcast event here
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mScreenStateReceiver, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mScreenStateReceiver);
}
Regards,