I have develop simple app for phone state listner for that I am starting service when call is in incoming mode and idle mode it is working fine but I want to pass data from broadcast receiver to my service I am starting my service from broadcast like this
Intent reivToServ = new Intent(context, RecorderService.class);
reivToServ.putExtra("number",phoneNumber);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(reivToServ);
}
else
{
reivToServ.putExtra("number", phoneNumber);
context.startService(reivToServ);
}
and for getting the data inside service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("command",intent.getStringExtra("number"));
}
But the intent is on null please any solution for this
Related
I have a service start in Activity A with
private void startService() {
Intent pushIntent = new Intent(this, MyService.class);
pushIntent.putExtra(MyService.TYPE_SCREEN, 1);
startService(pushIntent);
}
in my Service I get data from onStartCommand
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
typeScreen = intent.getExtras().getInt(TYPE_SCREEN);
return Service.START_STICKY;
}
I want when change from activity A to activity B, I will update type of screen from 1 to 2 in Service.
How I can do it?
Android only create one instance of a service.
Request that a given application service be started. The Intent can
either contain the complete class name of a specific service
implementation to start, or an abstract definition through the action
and other fields of the kind of service to start. If this service is
not already running, it will be instantiated and started (creating a
process for it if needed); if it is running then it remains running.
So in your case, the service is already running, then you just have to send the intent with the screen 2 extra. It will only call the onStartCommand Override method.
Intent pushIntent = new Intent(this, MyService.class);
pushIntent.putExtra(MyService.TYPE_SCREEN, 2);
startService(pushIntent);
In my Android app, I record a lot of things like GPS, barometric pressure, Bluetooth sensors. There is a "super" service which is started in the foreground:
Intent intent = new Intent(context, DataCollectorService.class);
ContextCompat.startForegroundService(context, intent);
The service itself has to start numerous child services like GPS-recording, Bluetooth sensor recording and the like. And the service creates a notification:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// . . .
Notification notification = new NotificationCompat.Builder(this, channelId)
// . . .
.build();
startForeground(NOTIFICATION_ID, notification);
mHandler.postDelayed(this::startChildServices, 100);
return START_STICKY;
}
private void startChildServices() {
// . . .
if (gpsEnabled) {
Intent intent = new Intent(this, GpsTrackingService.class);
bindService(intent, mGpsServiceConnection, Context.BIND_AUTO_CREATE);
startService(intent);
}
if (isPressureEnabled) {
Intent intent = new Intent(this, PressureService.class);
bindService(intent, pressureConnection, Context.BIND_AUTO_CREATE);
startService(intent);
}
// . . .
}
All works well, but a very small percentage of the users encounter crashes like this:
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
Actually, I start the "super" service in the foreground, as you can see.
Do I have to start the child services in the foreground as well?
Obviously, I don't want to have 3-7 notification icons in the users status bar.
I have an activity that starts a service. This service (Service-A) registers a broadcastreceiver with an intentfilter "ACTION_SCREEN_ON". When this broadcastreceiver runs it starts another service (Service-B) which updates my widgets periodically until screen is off.
This is how i register my broadcast receiver & how i implement my boradcast receiver
//Service that register my boradcastreceiver
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
IntentFilter filterScreen = new IntentFilter(Intent.ACTION_SCREEN_ON);
filterScreen.addAction(Intent.ACTION_SCREEN_OFF);
filterScreen.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filterScreen.addAction(Intent.ACTION_TIME_CHANGED);
mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filterScreen);
return START_STICKY;
}
//My broadcastreceiver
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
Intent service = new Intent(context, MinuteUpdateService.class);
context.startService(service);
}
else if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED))
{
Intent service = new Intent(context, MinuteUpdateService.class);
service.putExtra("oneTimeRun", true);
context.startService(service);
}
else if (intent.getAction().equals(Intent.ACTION_TIME_CHANGED))
{
Intent service = new Intent(context, MinuteUpdateService.class);
service.putExtra("oneTimeRun", true);
context.startService(service);
}
}
This flow usually works well. However sometimes my boradcastreceiver does not run as expected. It does not receive ACTION_SCREEN_ON broadcast. Usually this happens after long sleeps.
I suppose that Service-A killed/stopped by system and my broadcast is unregistered.
Is there any method that make this service/broadcast persistent? or is there another way which is more suitable for my intent?
I need to be able to detect when changes occur in contact data (any type of change to any contact in the address book).
I am using this ContentObserver:
public class ContactsContentObserver extends ContentObserver {
private Context context;
private Handler toastMessageHandler;
public ContactsContentObserver(Handler handler, Context ctx) {
super(handler);
context = ctx;
}
#Override
public void onChange(boolean selfChange) {
this.onChange(selfChange,null);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
// Change Detected! Do something.
}
}
I register this observer in a service like this:
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
registerContactsContentObserver();
return START_STICKY;
}
private void registerContactsContentObserver(){
ContactsContentObserver myObserver = new ContactsContentObserver(new Handler(), this);
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, myObserver);
}
I start this service in my main activity.
It works fine as long as the activity is open (even if in the background), and the onChange() method is called every time I change any contact data.
But it doesn't work at all if I manually close the app by clearing it from recent apps in android
Am I doing something wrong? Isn't the service supposed to run even when the app is closed?
I've been able to solve the issue with the help of pskink
Starting the service in the forground like this:
private void runAsForeground(){
Intent notificationIntent = new Intent(this, LauncherActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_ONE_SHOT);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("test")
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
}
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
runAsForeground();
registerContactsContentObserver();
return START_STICKY;
}
solved the issue.
Although, I still don't understand why the issue occurred in the first place, since, the service is sticky and supposed to run even if the app is closed. Even if android stopped the service to save memory, it is supposed to restart it.
Can somebody explain to me why starting the service in the foreground is any different than a regular sticky service in the background?
I'm having a problem with my IntentService. Every time I start my service, the onDestroy() method is called as soon as the service becomes idle. I set up my service to run in the foreground, and despite this the service is still being killed right away. I have only one other activity in my application, and it is not calling stopService().
Reading the developer docs gives me the impression that calling startForeground() will allow your service to persist, even when idle, except when there is an very high demand for memory, or am I reading this wrong?
My code below:
public class FileMonitorService extends IntentService {
public int mNotifyId = 273;
public FileMonitorService(){
super("FileMonitorService");
}
#Override
protected void onHandleIntent(Intent arg0) {
}
#Override
public void onDestroy() {
Toast.makeText(this, getText(R.string.toast_service_stop), Toast.LENGTH_SHORT).show();
stopForeground(true);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new Notification(R.drawable.icon, getText(R.string.notification_short), System.currentTimeMillis());
notification.flags|=Notification.FLAG_NO_CLEAR;
Intent notificationIntent = new Intent(this, FileMonitorActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_short),getText(R.string.notification_long), pendingIntent);
startForeground(mNotifyId, notification);
Toast.makeText(this, getText(R.string.toast_service_start), Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
}
You need to look into using a regular Service instead of an IntentService. IntentService is designed to keep running while it has work to do. Once you've finished your onStartCommand method, it tries to stop.
See the docs:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
(Emphasis mine)