Issues
Service is NOT running always even after I have used START_STICKY.
Sometimes I dont get any Toast Action for Outgoing call, is that mean service stops after some time ?
My Requirment
Application shows a Toast whenever user makes a outgoing call from the phone. For this I am using a BroadcastReceiver to tap the call action and a service (to run Receiver always). once I start this activity, it starts showing toast when a outgoing call get initiated ..but not Always.
Below is the complete code -
MainActivity.class
public class MainActivity extends Activity
{
CallNotifierService m_service;
boolean isBound = false;
private ServiceConnection m_serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName className, IBinder service)
{
m_service = ((CallNotifierService.MyBinder)service).getService();
Toast.makeText(MainActivity.this, "Service Connected", Toast.LENGTH_LONG).show();
isBound = true;
Intent intent = new Intent(MainActivity.this, CallNotifierService.class);
startService(intent);
}
#Override
public void onServiceDisconnected(ComponentName className)
{
m_service = null;
isBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, CallNotifierService.class);
bindService(intent, m_serviceConnection, Context.BIND_AUTO_CREATE);
}
.
.
.
}
CallNotifierService.class
public class CallNotifierService extends Service
{
private final IBinder myBinder = new MyBinder();
private static final String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0)
{
return myBinder;
}
#Override
public void onDestroy()
{
Log.d("service", "destroy");
this.unregisterReceiver(this.br_call);
Toast.makeText(CallNotifierService.this, "Receiver Un-Registered", Toast.LENGTH_LONG).show();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUTGOING_CALL);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
Toast.makeText(CallNotifierService.this, "onStartCommand Called", Toast.LENGTH_LONG).show();
return START_STICKY;
}
public class MyBinder extends Binder
{
CallNotifierService getService()
{
return CallNotifierService.this;
}
}
public class CallBr extends BroadcastReceiver
{
public CallBr() {}
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Action:"+intent.getAction(), Toast.LENGTH_LONG).show();
}
}
}
You are getting the wrong approach here, by mixing a simple idea (that would work if done correctly) with more complicated ideas (that cannot work).
Keep in mind: services are not "always running" components, even when using START_STICKY.
The Android system will not hesitate to kill your service if it needs memory somewhere else. START_STICKY only means that the Android system will re-start your service when it can, calling onStartCommand as specified in the documentation.
If you need a service to really stick around, then you must use a foreground service. But it will have consequences on the UI (annoying notification icon always showing), and battery life, and you do not need this here.
Now here is the magic trick: your app does not need to be running for your BroadcastReceiver to work. All you need to do is to register it in your AndroidManifest.xml with the correct intent-filter:
<receiver android:name=".broadcastreceivers.CallBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
(also make sure your app has the required permissions, namely PROCESS_OUTGOING_CALLS).
Then all you need in code is:
public class CallBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Action: " + intent.getAction(), Toast.LENGTH_LONG).show();
}
}
No activity (except to ask for the PROCESS_OUTGOING_CALLS permission on Android 6+), no service, nothing. Simple and battery-efficient !
The service does get re-created, not not re-started.
If you override the onCreate and do a Log.d or a Toast, you will see that it gets called after your app is destroyed.
So the trick to keep it running after it is recreated is to do your code on the onCreate method and use the onStartCommand just to return START_STICKY.
Related
I have an android device with an integrated barcode scanner. I'm setting up the service as follows:
public class BarcodeService extends Service {
private final LocalBinder binder = new LocalBinder();
public class LocalBinder extends Binder {
public BarcodeService getService() {
return BarcodeService.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
return binder;
}
#Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("ServiceStartArguments");
thread.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Get scanner
}
}
The service is also in the AndroidManifest.xml. The class that makes use of this service is:
public class BarcodeReader extends Activity {
private BarcodeService barcodeService;
private boolean isBound = false;
private ServiceConnection barcodeServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
barcodeService = ((BarcodeService.LocalBinder)service).getService();
isBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
barcodeService = null;
isBound = false;
}
};
#Override
protected void onStart() {
super.onStart();
if (!isBound) {
Intent intent = new Intent(this, BarcodeService.class);
startService(intent);
bindService(intent, barcodeServiceConnection, Context.BIND_AUTO_CREATE);
}
}
#Override
protected void onStop() {
super.onStop();
if (isBound) {
unbindService(barcodeServiceConnection);
}
}
}
However the service is not binding, ie. barcodeService is always null. The code never reaches onServiceConnected.
What am I missing? And is it necessary to use a class that extends Activity?
Common Android Service troubleshooting
Just some general remarks and stuff to check if your service is not starting.
Service class defined in Manifest
Common mistake is not to have the service in manifest (android doesn't warn you about that) or have it there but misspelled the class name.
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
Or you might have it in the manifest (or one of the manifests) but the final manifest after merging that is used within the apk doesn't have the service definition. For that check:
project_folder/app_folder/build/intermediates/manifests/full/...
A project clean and rebuild might help.
Check bindService return value
When debugging check the boolean return value on the bindService call to see if service was started successfully or not.
Debug Activity and Service implementation
Also the service might be running but not bind or might not execute anything hence have no visual effect that it's running in the background. For that use the debugger on both the bound Activity and the Service itself.
Check onBind, onStartCommand in Service class or even the onCreate there.
In Activity check bindService, ServiceConnection and so.
Resources
also check https://developer.android.com/guide/components/services.html
my Service never stop until I uninstall the app #HELP!
service class
public class LocationService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
GPSTracker myGps = new GPSTracker(getApplicationContext());
Log.e("tracking...","");
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public boolean stopService(Intent name) {
GPSTracker myGps = new GPSTracker(getApplicationContext());
Log.e("STOPPED!","");
return super.stopService(myGps);
}
}
** Start the Service At the Login Activity**
Intent locationService = new Intent(Login.this, LocationService.class);
startService(locationService);
**Stop the service At the employee Activity in option selected menu **
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent serviceIntent;
int id = item.getItemId();
if (id == R.id.LogOut) {
serviceIntent = new Intent(Employee.this, LocationService.class);
stopService(serviceIntent);
Log.e("OUT"," ");
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In the 2 activities A and B u have, you should unbind service in B onStop(), then you can call stopService in A. Simply putting stopService(serviceIntent); might give you and error about leaked service connection
protected ServiceConnection mServerConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext is defined upper in code, I think it is not necessary to explain what is it
mContext.bindService(i, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(i);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
and see in your code what you have done is u have stopped the service but i dont see you unbinding it, the correct procedure would be unbind it then stop it.
Dont use the command startService(service).
To start the service at the beginning of the app just bind it to all your activities. This way, when the activities are destroyed, the service stops.
Explained thoroughly HERE
Also, if you want the service to end when the app is closed(but not destroyed), just add unBindService method to an overrided onStop method.
I am trying to make my own MusicPlayer for android. Where i came to a problem is running some things in background. Main activity manages GUI and up to now all the songs are playing. I wanted to separate GUI and music playing classes. I want to put music managing part in Service and leave other things as they are now.
My problem is that i can't organize communication between Activity and Service as lot of communication is happening between them including moving objects in both directions. I tried many techniques that I searched here on Stack Overflow but every time I had problems. I need Service to be able to send objects to Activity and vice versa. When I add widget i also want it to be able to communicate with Service.
Any tips are appreciated, if you need source code place comment bellow but now in this transition it became chaotic.
Is there any more advanced tutorial on this than calling one method that returns random number from service? :P
EDIT: Possible solution is to use RoboGuice library and move objects with injection
I have implemented communication between Activity and Service using Bind and Callbacks interface.
For sending data to the service I used Binder which retruns the Service instace to the Activity, and then the Activity can access public methods in the Service.
To send data back to the Activity from the Service, I used Callbacks interface like you are using when you want to communicate between Fragment and Activity.
Here is some code samples for each:
The following example shows Activity and Service bidirectional relationship:
The Activity has 2 buttons:
The first button will start and stop the service.
The second button will start a timer which runs in the service.
The service will update the Activity through callback with the timer progress.
My Activity:
//Activity implements the Callbacks interface which defined in the Service
public class MainActivity extends ActionBarActivity implements MyService.Callbacks{
ToggleButton toggleButton;
ToggleButton tbStartTask;
TextView tvServiceState;
TextView tvServiceOutput;
Intent serviceIntent;
MyService myService;
int seconds;
int minutes;
int hours;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent(MainActivity.this, MyService.class);
setViewsWidgets();
}
private void setViewsWidgets() {
toggleButton = (ToggleButton)findViewById(R.id.toggleButton);
toggleButton.setOnClickListener(btListener);
tbStartTask = (ToggleButton)findViewById(R.id.tbStartServiceTask);
tbStartTask.setOnClickListener(btListener);
tvServiceState = (TextView)findViewById(R.id.tvServiceState);
tvServiceOutput = (TextView)findViewById(R.id.tvServiceOutput);
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
Toast.makeText(MainActivity.this, "onServiceConnected called", Toast.LENGTH_SHORT).show();
// We've binded to LocalService, cast the IBinder and get LocalService instance
MyService.LocalBinder binder = (MyService.LocalBinder) service;
myService = binder.getServiceInstance(); //Get instance of your service!
myService.registerClient(MainActivity.this); //Activity register in the service as client for callabcks!
tvServiceState.setText("Connected to service...");
tbStartTask.setEnabled(true);
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
Toast.makeText(MainActivity.this, "onServiceDisconnected called", Toast.LENGTH_SHORT).show();
tvServiceState.setText("Service disconnected");
tbStartTask.setEnabled(false);
}
};
View.OnClickListener btListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v == toggleButton){
if(toggleButton.isChecked()){
startService(serviceIntent); //Starting the service
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE); //Binding to the service!
Toast.makeText(MainActivity.this, "Button checked", Toast.LENGTH_SHORT).show();
}else{
unbindService(mConnection);
stopService(serviceIntent);
Toast.makeText(MainActivity.this, "Button unchecked", Toast.LENGTH_SHORT).show();
tvServiceState.setText("Service disconnected");
tbStartTask.setEnabled(false);
}
}
if(v == tbStartTask){
if(tbStartTask.isChecked()){
myService.startCounter();
}else{
myService.stopCounter();
}
}
}
};
#Override
public void updateClient(long millis) {
seconds = (int) (millis / 1000) % 60 ;
minutes = (int) ((millis / (1000*60)) % 60);
hours = (int) ((millis / (1000*60*60)) % 24);
tvServiceOutput.setText((hours>0 ? String.format("%d:", hours) : "") + ((this.minutes<10 && this.hours > 0)? "0" + String.format("%d:", minutes) : String.format("%d:", minutes)) + (this.seconds<10 ? "0" + this.seconds: this.seconds));
}
}
And here is the service:
public class MyService extends Service {
NotificationManager notificationManager;
NotificationCompat.Builder mBuilder;
Callbacks activity;
private long startTime = 0;
private long millis = 0;
private final IBinder mBinder = new LocalBinder();
Handler handler = new Handler();
Runnable serviceRunnable = new Runnable() {
#Override
public void run() {
millis = System.currentTimeMillis() - startTime;
activity.updateClient(millis); //Update Activity (client) by the implementd callback
handler.postDelayed(this, 1000);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Do what you need in onStartCommand when service has been started
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//returns the instance of the service
public class LocalBinder extends Binder{
public MyService getServiceInstance(){
return MyService.this;
}
}
//Here Activity register to the service as Callbacks client
public void registerClient(Activity activity){
this.activity = (Callbacks)activity;
}
public void startCounter(){
startTime = System.currentTimeMillis();
handler.postDelayed(serviceRunnable, 0);
Toast.makeText(getApplicationContext(), "Counter started", Toast.LENGTH_SHORT).show();
}
public void stopCounter(){
handler.removeCallbacks(serviceRunnable);
}
//callbacks interface for communication with service clients!
public interface Callbacks{
public void updateClient(long data);
}
}
Update: July 10 2016
IMO I think using BroadcastReceiver for custom events is better way
as the Messengers mentioned don't handle activity recreation on device
rotation as well as possible memory leaks.
You may create custom BroadCast Receiver for events in the activity, Then you may also use Messengers.
In your Activity
create a MessageHandler class as
public static class MessageHandler extends Handler {
#Override
public void handleMessage(Message message) {
int state = message.arg1;
switch (state) {
case HIDE:
progressBar.setVisibility(View.GONE);
break;
case SHOW:
progressBar.setVisibility(View.VISIBLE);
break;
}
}
}
Now you can have it's instance as
public static Handler messageHandler = new MessageHandler();
Start your Service with this Handler object as an extra data as
Intent startService = new Intent(context, SERVICE.class)
startService.putExtra("MESSENGER", new Messenger(messageHandler));
context.startService(startService);
In your Service you receive this object from the intent and initialize the Messenger variable in Service as
private Messenger messageHandler;
Bundle extras = intent.getExtras();
messageHandler = (Messenger) extras.get("MESSENGER");
sendMessage(ProgressBarState.SHOW);
And then write a method sendMessage to send messages to activity.
public void sendMessage(ProgressBarState state) {
Message message = Message.obtain();
switch (state) {
case SHOW :
message.arg1 = Home.SHOW;
break;
case HIDE :
message.arg1 = Home.HIDE;
break;
}
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
The sample code above shows and hides a ProgressBar in Activity as messages are received from Service.
Intents are good solution for communication between Activitiy and Service.
A fast solution for receive intents in your service is subclassing IntentService class. It handles asynchronous requests expressed as Intents using a queue and worker thread.
For communication from service to Activity you can broadcast the intent but instead of using normal sendBroadcast() from Context, a more efficent way is to use LocalBroadcastManager from support library.
Example service.
public class MyIntentService extends IntentService {
private static final String ACTION_FOO = "com.myapp.action.FOO";
private static final String EXTRA_PARAM_A = "com.myapp.extra.PARAM_A";
public static final String BROADCAST_ACTION_BAZ = "com.myapp.broadcast_action.FOO";
public static final String EXTRA_PARAM_B = "com.myapp.extra.PARAM_B";
// called by activity to communicate to service
public static void startActionFoo(Context context, String param1) {
Intent intent = new Intent(context, MyIntentService.class);
intent.setAction(ACTION_FOO);
intent.putExtra(EXTRA_PARAM1, param1);
context.startService(intent);
}
public MyIntentService() {
super("MyIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_FOO.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM_A);
// do something
}
}
}
// called to send data to Activity
public static void broadcastActionBaz(String param) {
Intent intent = new Intent(BROADCAST_ACTION_BAZ);
intent.putExtra(EXTRA_PARAM_B, param);
LocalBroadcastManager bm = LocalBroadcastManager.getInstance(this);
bm.sendBroadcast(intent);
}
}
Example Activity
public class MainActivity extends ActionBarActivity {
// handler for received data from service
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MyIntentService.BROADCAST_ACTION_BAZ)) {
final String param = intent.getStringExtra(EXTRA_PARAM_B);
// do something
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction(MyIntentService.BROADCAST_ACTION_BAZ);
LocalBroadcastManager bm = LocalBroadcastManager.getInstance(this);
bm.registerReceiver(mBroadcastReceiver, filter);
}
#Override
protected void onDestroy() {
LocalBroadcastManager bm = LocalBroadcastManager.getInstance(this);
bm.unregisterReceiver(mBroadcastReceiver);
super.onDestroy();
}
// send data to MyService
protected void communicateToService(String parameter) {
MyIntentService.startActionFoo(this, parameter);
}
}
I think there is a problem with the correct answer. I have not enough reputation to comment on it.
Right in the answer:
Activity call bindService() to get pointer to Service is ok. Because service context is maintained when connection is maintained.
wrong in the answer:
service pointer to Activity class to call back is bad way. Activity instance maybe not null during Activity context is being Release => exception here.
solution for the wrong in the answer:
service send intent to Activity. and Activity receiver intent via BroadcastReceiver.
Note:
in this case, Service and Activity in the same Process, you should use LocalBroadcastManager to send intent. It make performance and security better
This is a simple example of communication between activity and service
Activity
MyReceiver myReceiver; //my global var receiver
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layourAwesomexD);
registerReceiver();
}
//When the activity resume, the receiver is going to register...
#Override
protected void onResume() {
super.onResume();
checkStatusService(); // verficarStatusServicio(); <- name change
registerReceiver();
}
//when the activity stop, the receiver is going to unregister...
#Override
protected void onStop() {
unregisterReceiver(myReceiver); //unregister my receiver...
super.onStop();
}
//function to register receiver :3
private void registerReceiver(){
//Register BroadcastReceiver
//to receive event from our service
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyService.SENDMESAGGE);
registerReceiver(myReceiver, intentFilter);
}
// class of receiver, the magic is here...
private class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
//verify if the extra var exist
System.out.println(arg1.hasExtra("message")); // true or false
//another example...
System.out.println(arg1.getExtras().containsKey("message")); // true or false
//if var exist only print or do some stuff
if (arg1.hasExtra("message")) {
//do what you want to
System.out.println(arg1.getStringExtra("message"));
}
}
}
public void checkStatusService(){
if(MyService.serviceStatus!=null){
if(MyService.serviceStatus == true){
//do something
//textview.text("Service is running");
}else{
//do something
//textview.text("Service is not running");
}
}
}
Service
public class MyService extends Service {
final static String SENDMESAGGE = "passMessage";
public static Boolean serviceStatus = false;
#Override
public void onCreate() {
super.onCreate();
serviceStatus=true;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {return null;}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//you service etc...
passMessageToActivity("hello my friend this an example of send a string...");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
passMessageToActivity("The service is finished, This is going to be more cooler than the heart of your ex...");
System.out.println("onDestroy");
serviceStatus=false;
}
private void passMessageToActivity(String message){
Intent intent = new Intent();
intent.setAction(SENDMESAGGE);
intent.putExtra("message",message);
sendBroadcast(intent);
}
}
if we don't unregister BroadcastReceiver we will have an error, you need to unregister when the activity go onPause, onStop, onDestroy...
if you don't register BroadcastReceiver when you back to activity, it will not listen anything from the service... the service will send information to BroadcastReceiver but it will not receive anything because it isn't registered.
When you create more than one service, the following services are going to begin in onStartCommand.
You can pass information to service with intent and you get it in onStartCommand
Difference about return in onStartCommand: Difference between START_STICKY and START_REDELIVER_INTENT? and check the official website of google: Services
The best way in this case is to communicate by doing broadcasting from your service for different actions and receiving it in your activity. You can create a custom broadcast and send some codes defining specific events like complete, change, prepare etc...
Most easy and efficient way will be using EventBus from GreenRobot.
Use simple 3 steps:
1 Define events
public static class MessageEvent { /* Additional fields if needed */ }
2 Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
3 Post events:
EventBus.getDefault().post(new MessageEvent());
Very easy yet powerful way is to use EventBus you can add it to your gradle build and enjoy the easy publisher/subscriber pattern .
I am trying to set up a service that checks when a new update of an activity is installed in a device. I have already done so within an application activity, declaring the Broadcastreceiver in the manifest and it works perfectly.
However, when I try to run that receiver within a Service and dynamically declare it, my onReceive never gets called. This is my Service code:
public class UpdateService extends Service {
private static String mPackage = "com.my.package";
private static String mActivityName = "myActivity";
private BroadcastReceiver mUpdateReceiver;
#Override
public void onCreate() {
super.onCreate();
mUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("mTag","In the BroadcastReceiver onReceive()");
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_PACKAGE_REPLACED)) {
// Log that a new update is has been found
Log.d("mTag","New version of the app has been installed.");
Log.d("mTag", "Intent data: " + intent.getDataString());
Log.d("mTag","My package: " + mPackage);
}
}
};
Log.d("mTag","In the service onCreate() method.");
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
registerReceiver(mUpdateReceiver,filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("mTag","UpdateService started");
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mUpdateReceiver);
Log.d("mTag","Service destroyed");
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
The Log in the Service onCreate() gets called, which tells me that the service is up and running. However, after installing and replacing some apps through the adb, none of the logs in the BroadcastReceiver the method onReceive() get called.
This is my MainActivity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, UpdateService.class));
}
}
Do you guys have any ideas why the onReceive() does not get called?
Thank you.
I based my code in these two references:
BroadcastReceiver within a Service
How to know Android app upgraded?
you should add the data schema to your IntentFilter.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
registerReceiver(mUpdateReceiver,filter);
If you are trying to listen to the ACTION_PACKAGE_REPLACED broadcast, this cannot be done from service. Most probably, the replacement will happen when your application is closed. That`s why you will not listen to it.
You should register from the Manifest to let your OS know that you want to listen to this Intent then Create a class that extentsBroadcastReceiver` as the following:
Manifest:
<receiver android:name="PackageChangeReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Receiver:
public class PackageChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) && intent.getDataString().contains(context.getPackageName())) {
Log.d("Tag", "Package has been replaced");
Log.d("Tag", "Intent data: " + intent.getDataString());
Log.d("Tag", "Action: " + intent.getAction());
}
}
}
I have checked if intent.getDataString().contains(context.getPackageName()) to make sure that the replacement of the package is mine not any other application.
I'm starting a service from an Activity. The service registers for Battery Changed broadcast Receiver. I receive broadcasts as long as the screen is ON. Once the screen is turned OFF, I stop receiving broadcasts, however, the service doesn't die.
My activity code,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this.getApplicationContext();
Intent intent = new Intent(this,BatteryStatusService.class);
startService(intent);
}
and my service code,
public class BatteryStatusService extends Service{
private final static String TAG = BatteryStatusService.class.getSimpleName();
private BroadcastReceiver timeTickReceiver;//changeReceiver;
private boolean registered = false;
public class LocalBinder extends Binder {
BatteryStatusService getService() {
return BatteryStatusService.this;
}
}
private final IBinder mBinder = new LocalBinder();
#Override
public void onStart(Intent intent, int startId){
Log.i(TAG,"Starting service");
IntentFilter filter = new IntentFilter();
filter.addAction(Constants.ACTION_BATTERY_CHANGED);
timeTickReceiver = new TimeTickReceiver();
this.getApplicationContext().registerReceiver(timeTickReceiver, filter);
registered = true;
}
#Override
public void onDestroy(){
Log.d(TAG,"Stopping service");
if(registered){
this.getApplicationContext().unregisterReceiver(timeTickReceiver);
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
public class TimeTickReceiver extends BroadcastReceiver {
private String action = null;
private final String TAG = TimeTickReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if(action.equals(Constants.ACTION_BATTERY_CHANGED)){
Log.d(TAG,"I got action = "+action);
}
}
}
}
}
use AlarmManager and get last broadcasted level with
Intent BATTERYintent=this.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
However there are mobiles where it would work either. I have t-mobile MOVE which will not update battery value/broadcast no matter what in sleep mode... but most mobiles will do it as they should
by the way dont listen to dcanh121 there are cases when u need to get battery level even when phone is in sleepmode.
Once the screen is turned OFF, I stop receiving broadcasts, however, the service doesn't die.
When the screen is turned off, shortly thereafter the device goes into sleep mode. Your code does not execute again until something wakes up the device from sleep mode.
Also:
You do not need to use getApplicationContext() here
You do not need a Binder here, since you are not binding to the service, so just have onBind() return null
You need to have some code somewhere to stop this service, so it does not run forever
why don't you try by using onResume() and onPause()