I'm implementing an app that requires to monitor the device's battery level. So I implemented a Service like this:
public class BatteryService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
return super.onStartCommand(intent, flags, startId);
}
private final BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Save the data
}
};
}
I start this service in my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, BatteryService.class));
}
}
and in a android.intent.action.BOOT_COMPLETED receiver:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,BatteryService.class));
}
}
I have two problems:
Testing app after some time, it stops registering battery changed events
After rebooting the phone the app crashes with the following error
Caused by java.lang.IllegalStateException: Not allowed to start service Intent {...} app is in background
Maybe my questions are self-related:
How do I avoid the service to stop running after some time?
How do I avoid the crash on boot? I have read that using "startForegroundService" but, it does require to present a notification to the user.
How can I run in background and monitor the battery properly without constantly showing a notification?
Thanks!
Actually it was because of Android built-in security. They discouraged background services for user's protection. To allow such action, user must be aware that your service is running by starting it in foreground.
Intent intent = new Intent(this, typeof(SomeActivityInYourApp));
PendingIntent pi = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.Drawable.my_icon);
builder.setTicker("App info string");
builder.setContentTitle("Hey there");
builder.setContentText("My battery service is running!")
builder.setContentIntent(pi);
builder.setOngoing(true);
Notification notification = builder.build();
startForeground(SERVICE_NOTIFICATION_ID, notification);
Related
I created an Android application to get all the call logs after the user ends the call. I used Broadcast Receiver to identify the changes then Run the service to get the information about the last call. But sometimes App is killed by the system after one or two days. I read the Broadcast Documentation, Android Service Documentation, and Android <OREO Restriction. Is there any way to keep the Call Broadcast Receiver all the time?
Is there any way to use work manager?
Is there any good approaches, please share here
Service class
public class CallReceiver extends BroadcastReceiver{
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, HammerService.class);
context.startForegroundService(startServiceIntent);
}
}
Service class
public class HammerService extends Service {
#Override
public void onCreate() {
super.onCreate();
IntentFilter ifilter = new IntentFilter();
ifilter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
registerReceiver(receiver, ifilter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Hammer Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
//do heavy work on a background thread
//stopSelf();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if(action.equals("android.provider.Telephony.SMS_RECEIVED")){
//action for sms received
}
else if(action.equals(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED)){
runfirstTime(context,intent);
}
}
};
I'm creating an app that uses two foreground services:
One for getting the Location
The other to updload it to a server (every 30secs)
I'm currently testing my app with a device running Nougat but I'd like to make it Oreo-ready.
First I was using a different Notification for each foreground service, but then I wanted to try using the same notification for both, as in this SO answer.
If I stop any of those services by calling stopService(intent) then the notification disappears even if the other foregroundService is still running.
Is there a way to keep the notification even after stopping one of the services?
Then, when both services are down I will manually remove the notification
EDIT added code as requested
This is how my services looks like (they are basically identical):
public class TrackingService extends Service{
#Override
public void onCreate() {
startForeground(getNotificationId(), getNotification(this));
// Some other tracking/server stuff
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Some other tracking/server stuff
return START_STICKY;
}
#Override
public void onDestroy() {
stopForeground(false);
}
I'm starting them with:
Intent intent = new Intent(getApplicationContext(), TrackingService.class);
startService(intent);
And then stopping with:
Intent intent = new Intent(getApplicationContext(), TrackingService.class);
stopService(intent);
I've read that calling stopService(intent) will also remove that service from the foreground. So the calling to stopForeground(false) is redundant, but I leave it anyway.
And the singleton for the Notification is:
public abstract class SingleNotificacion {
private static final int NOTIFICATION_ID = 1999;
private static Notification notification;
public static Notification getNotification(Context context) {
if(notification == null) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "default")
.setSmallIcon(R.drawable.ic_stat_notify)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(Notification.CATEGORY_SERVICE)
.setContentTitle(context.getString(R.string.settings_status_on_summary))
.setColor(ContextCompat.getColor(context, R.color.colorPrimaryDark));
notification = builder.build();
}
return notification;
}
public static int getNotificationId() {
return NOTIFICATION_ID;
}
public static void cancelNotification(Context context){
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID);
}
}
I've also try setting onGoing(true) and 'autoCancel(false)' when creating the Notification with no luck
I have a Service that listens to both incoming and outgoing calls.The Service runs when the app is started and keeps on running for some time even after the app is closed.But somehow is the Service is destroyed or something later.I have put START_STICKY as the return of the startCommand() method.I know the System kills the Service when the memory is high.But then how are the call recording apps able to listen to calls continuously?Is there a work around for this kind of problem?How do I make my app listen to phone calls continuously?
Code
PhoneListenerService.class
public class PhoneListenerService extends Service{
private TelephonyManager telephonyManager;
private File file;
OutgoingReceiver outgoingReceiver;
#Override
public void onCreate()
{
super.onCreate();
outgoingReceiver=new OutgoingReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(outgoingReceiver,intentFilter);
file=new File(Environment.getExternalStorageDirectory().getAbsolutePath());
telephonyManager=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
file=new File(Environment.getExternalStorageDirectory(),"AutoCall");
if (!file.exists())
{
Log.e("File","Created");
file.mkdir();
}
else
{
Log.e("File",file.getPath());
}
telephonyManager.listen(new TeleListener(getApplicationContext(),file.getAbsolutePath()),PhoneStateListener.LISTEN_CALL_STATE);
Log.e("Oncreate","Service");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("OnCommand","Service");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(outgoingReceiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public class OutgoingReceiver extends BroadcastReceiver {
public OutgoingReceiver()
{
}
#Override
public void onReceive(Context context, Intent intent) {
Log.e("Out","Track");
String phone_number=intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context,"Outgoing call identified",Toast.LENGTH_SHORT).show();
}
}
}
Start the service as FOREGROUND Service like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Register your reporting alarms here.
Log.e("SmsAndCallService", "IN onStartCommand");
startForeground(105, getCompatNotification());
return Service.START_STICKY;
}
private Notification getCompatNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "105");
builder.setSmallIcon(R.mipmap.ic_launcher).setContentTitle(getString(R.string.app_name) + " running").setTicker("Recording");
Intent intent = new Intent(new Intent(getApplicationContext(), SplashActivity.class));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 2003, intent, 0);
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
return notification;
}
So system cant kills this service when system run out of resources. `
FOREGROUND SERVICE means some sort of notification stuff keep showing to make the system to aware that service is still running.
Use a static system define broadcast receiver for incoming calls.don't forgot to declare this in manifest
Yea.I use MediaRecorder for that.I have a question.If the deveice is restarted will the service and receiver still run in the background
Like this way you need to have broadcast receiver for reboot restarting your service and jobscheduler for Higher versoin than marshmallow Android 6.0
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
Intent iService = new Intent(context, PhotoService.class);
context.startService(iService);
} else
JobInfoServ.scheduleJob(context);
}
}
AndroidManifest.xml
<receiver
android:name="com.your.package.broadcast.BootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I want to create an alarm application, which will sound the alarm when you set the time. I've got it to work partially. I'm stuck at the alarm not being set after the app is closed via recent tray(Not with force stop). To tackle this, I created a service which will run in the background(even if the app is closed) and will sound the alarm.
My problem right now, is that even after using a service, I'm unable to sound the alarm after the app is closed. However, the service seems to be running after the closure of the app(I've seen in running apps. It says My App has a service running in the background).
NOTE : I've also bound the service with my activity so that I can use its methods.
NOTE 2 : The service sounds the alarm when the application is open, Only fails to do so when the app is closed.
This is my code :
Calling the service from my Activity :
public void startOnClick(View view) {
int aHour = alarmTimePicker.getCurrentHour();
int aMin = alarmTimePicker.getCurrentMinute();
Alarms alarm = new Alarms(aHour, aMin); //I've created an Alarms class Seperately
myService.setAlarm2(alarm); //Setting the alarm via service
Toast.makeText(this, "Alarm SET.", Toast.LENGTH_LONG).show();
}
In MyService : `package com.wars.tap.tapwars;
public class MyService extends Service {
private final IBinder myBinder = new MyBinder();
Alarms alarm = new Alarms();
private PendingIntent pendingIntent;
private AlarmManager alarmManager;
private ServiceCallBacks serviceCallbacks;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return myBinder;
}
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void setCallbacks(ServiceCallBacks callbacks) {
serviceCallbacks = callbacks;
}
public void setAlarm2(final Alarms alarm){
Runnable r = new Runnable() {
#Override
public void run() {
try {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, alarm.get_hour());
calendar.set(Calendar.MINUTE, alarm.get_min());
AlarmManager AM = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(MyService.this, AlarmReceiver.class);
i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
pendingIntent = PendingIntent.getBroadcast(MyService.this, 934, i, PendingIntent.FLAG_UPDATE_CURRENT);
AM.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
} catch (Exception e) {
}
}
};
Thread t = new Thread(r);
t.start();
}
}
`
So, the setAlarm2 is the method I'm using in the service to sound the alarm. It's working when the app is open, but fails to work when the app is being closed. As you can see, this is my first post on StackOverflow and I'm also new to android programming. I've been stuck with this for a long time and would appreciate some help. Thank you.
Your alarm could be working, but the notification center is not aware of allowing your app any privileges to highlight the event that is occurring. Check out this link here for details on Notifications.
EDIT
Check out the code below I extracted from a previous project. I left out the necessary parts:
public class MyClass extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onTaskRemoved(Intent rootIntent) {
// Input your code here prior to exit.
stopSelf();
}
}
I want to make an timer which starts counting when the Android device is woken up and stops when the Android device is set to sleep. I found nothing, how a activity could be triggered
by wake up/sleep.
I hope you can help me with my problem
I used a BroadcastReceiver like timonvlad said but ACTION_SCREEN_ON and ACTION_SCREEN_OFF could not be called by XML so I created an service. The service has to be registered in the XML then I used this code
public class OnOffReceiver extends Service {
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
//This happens when the screen is switched off
}
}, new IntentFilter(Intent.ACTION_SCREEN_OFF));
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
//This happens when the screen is turned on and screen lock deactivated
}
}, new IntentFilter(Intent.ACTION_USER_PRESENT));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Use BroadcastReceiver and service to catch Screen_on and_off.... For example like ...
public class InternetReceiver extends BroadcastReceiver{
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
Intent i = new Intent(context, InternetService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
}
You should create a BroadcastReceiver that listens to the ACTION_BOOT_COMPLETED intent.
In the implementation, you have to store the timestamp of when that intent was received.
After that, you can create an activity that retrieves that timestamp, and calculates how much time has the phone been running.
Set up repeating event that will be fired when the device is awake:
AlarmManager.setRepeating(AlarmManager.RTC, time, period, pendingIntent);
Then catch those alarms and increment your timer counter, it will be counting when device is awake.
Don't start activity when device wakes up. Users will not be happy about such behavior of an app. Use notifications instead.