How to prevent restarting a running Service - Android - java

i'm want to do long background work
also i want to be able to show progress with statistics in ui anytime user goes to a activity also with updating notification.
i start a Service in START_STICKY mode then i bind it to my activity and run the proccess with an public method of Service.
everything works well until i close my app from recent apps.
it destroys and restart my running Service.
that's the problem. "i don't want my running service to restart"
i want my service to keep running without termination and without restarting.
how can i do what i want to do?
why os restart a running service: / thou
i tried START_NOT_STICKY but it's closing the service too.

On Android 6+, a foreground service will not be stopped when the user removes the app from recents. You can make your service a foreground service by adding this code to onCreate():
final Intent launcherIntent = new Intent();
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, launcherIntent, 0);
final Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Test Notification")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent);
final Notification notification;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.build();
}
else {
//noinspection deprecation
notification = builder.getNotification();
}
this.startForeground(NOTIFICATION_ID, notification);
Prior to Android 6, services are always killed when the user removes the task from recents. There is nothing you can do about it except shut down cleanly in onTaskRemoved().

Try using foreground service:
In method where you start service:
Intent startIntent = new Intent(MainActivity.this, ForegroundService.class);
startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(startIntent);
Now in onStartCommand():
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
Log.i(LOG_TAG, "Received Start Foreground Intent ");
Toast.makeText(this, "Service Started!", Toast.LENGTH_SHORT).show();
Read more Simple foreground service
OR you can try something like this:
from onStartCommand() need to return START_STICKY
override in your service onDestroy method:
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent();
broadcastIntent.putExtra("broadcast.Message", "alarm, need to restart service");
sendBroadcast(broadcastIntent);
}
Now need to implement broadcast receiver:
public class RestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startService(new Intent(context, YourService.class));
}
}

check if service is running or not
if(!isBackgroundServiceRunning(BackgroundServices.class))
{
Intent intent = new Intent(this,BackgroundServices.class);
startService(intent);
}
private boolean isBackgroundServiceRunning(Class<?> service)
{
ActivityManager manager = (ActivityManager)(getApplicationContext().getSystemService(ACTIVITY_SERVICE));
if (manager != null)
{
for(ActivityManager.RunningServiceInfo info : manager.getRunningServices(Integer.MAX_VALUE))
{
if(service.getName().equals(info.service.getClassName()))
return true;
}
}
return false;
}

Related

BroadcastReceiver doesn't work for the second time

I'm trying to schedule notifications with AlarmManager It works perfectly when I schedule one notification but when I schedule two notification, the first notification is okay but the second one not works.
I figured out opening the app after few minutes will notify the second notification. I think something is wrong with my BroadcastReceiver
MainActivity.java
Intent intent = new Intent(context,NotificationClass.class);
intent.putExtra("notification_id", id);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,id,intent,PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),pendingIntent);
Notification.java
public class NotificationClass extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int id = intent.getIntExtra("notification_id",0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,"1")
.setContentTitle("Notification")
.setContentText("Content")
.setSmallIcon(R.drawable.notif_ic);
Notification notification = builder.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("1","test", NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(id,notification);
}
AndroidManifest.xml
<receiver android:name=".NotificationClass" ></receiver>
I don't know what is wrong with my code. Can anybody help me with this?
Broadcast receiver to receive the data:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String alertMessage = intent.getStringExtra("type");
doNotificationAlertWorkHere(alertMessage);
}
};
Register & Unregister your broadcast to avoid static leaks.
via the Android manifest file. (Statically)
<receiver android:name="YourBroadcastReceiverName"> </receiver>
via the Context.registerReceiver() and Context.unregisterReceiver() methods. (Dynamically)
#Override
protected void onPause() {
super.onPause();
// unregister broadcast
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
}
#Override
protected void onResume() {
super.onResume();
// register broadcast
IntentFilter filter = new IntentFilter(Constants.ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
}
Send Broadcast like:
// public static final String ACTION = "ALERT";
Intent intent = new Intent(Constants.ACTION);
intent.putExtra("type", "SUP BRO. Stay Inside");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Knowledge Note :- Broadcast receiver is like a Cannon-fire to score a hit, you have to determine what to fire (eg. msg), where to fire (eg. activity). Load & unload the cannon to score another hit. (eg. Register & Unregister)
I have tried it and it is working. Add your notification code inside onReceive.
Broadcast Receiver
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
/*
Your implementation
*/
}
}
Mainfest
<receiver
android:name=".AlarmReceiver"
android:exported="true"
android:enabled="true" />
Creating pending intents
val alarmManager = activity.getSystemService(Activity.ALARM_SERVICE) as AlarmManager
val alarmIntent = Intent(activity.applicationContext, AlarmReceiver::class.java) // AlarmReceiver1 = broadcast receiver
val calendar = Calendar.getInstance()
calendar.timeInMillis = timeInMilliSeconds
val pendingIntent = PendingIntent.getBroadcast(activity, timeInMilliSeconds.toInt(), alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT)
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
First, make sure your notification Id is difference every single time you create a notification
Second, you miss tag intent-filter inside tag receive in manifest. pls check this https://developer.android.com/guide/components/broadcasts.
Hope this help!

Cant get Extras from intent when application is in background

I try to execute a function in my MainActivity when a notification is clicked.
The function needs a data that I put in intent extras.
The problem is when I click the notification when the application is running the function is executed, but when I click the notification when the application is in the background, the function isn't executed. I've checked it and it's because the data that I put in intent extras is empty when the application is in the background.
How can I solve this problem? Thanks!
This is the response i receive :
{
"to":"blablabla",
"notification": {
"body":"Sentiment Negative from customer",
"title":"Mokita"
},
"data" : {
"room_id":1516333
}
}
This is my notification code :
public void onMessageReceived(RemoteMessage message) {
super.onMessageReceived(message);
Log.d("msg", "onMessageReceived: " + message.getData().get("room_id"));
String roomId = message.getData().get("room_id");
Intent intent = new Intent(this, HomePageTabActivity.class);
intent.putExtra("fromNotification", true);
intent.putExtra("roomId", roomId);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
String channelId = "Default";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(message.getNotification().getTitle())
.setContentText(message.getNotification().getBody())
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Default channel", NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
manager.notify(0, builder.build());
}
}
And this is the function and how i executed it in MainActivity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawer);
onNewIntent(getIntent());
}
#Override
public void onNewIntent(Intent intent){
Bundle extras = intent.getExtras();
if(extras != null){
if(extras.containsKey("fromNotification") || extras.containsKey("roomId")) {
openChatRoom(Long.valueOf(extras.getString("roomId")));
}else if(extras.containsKey("fromNotification") && extras.containsKey("roomId")){
openChatRoom(Long.valueOf(extras.getString("roomId")));
}else{
Log.e("EXTRAS room",""+extras.getString("roomId"));
Log.e("EXTRAS STATUS",""+extras.getBoolean("fromNotification"));
}
}else{
Toast.makeText(HomePageTabActivity.this,"Empty",Toast.LENGTH_SHORT).show();
}
}
public void openChatRoom(long roomId){
Log.d("LONG ROOM",""+roomId);
QiscusRxExecutor.execute(QiscusApi.getInstance().getChatRoom(roomId),
new QiscusRxExecutor.Listener<QiscusChatRoom>() {
#Override
public void onSuccess(QiscusChatRoom qiscusChatRoom) {
startActivity(GroupRoomActivity.
generateIntent(HomePageTabActivity.this, qiscusChatRoom));
}
#Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
});
}
Firebase has two types of messages: notification messages and data messages. If you want FCM SDK to handle the messages by its own, you need to use notification. When the app is inactive, FCM will use notification body to display the messages. In this state, onMessageReceived also will not be triggered. If you want app to process the messages, you need to use data. You might need to change push notification payload from
{
"message":{
"token":"xxxxx:...",
"notification":{
"title":"Your title",
"body":"Your message"
}
}
}
to
{
"message":{
"token":"xxxxx:...",
"data":{
"title":"Your title",
"body":"Your message",
"fromNotification":"true",
"roomId":"123"
}
}
}
You also need to process the messages in onMessageReceived(RemoteMessage remoteMessage) accordingly. You can read about notification behaviour in Notifications and data messages.
these payloads will be delivered to the activity you are specifying in the pending intent. so when the user clicks on your notification, HomePageTabActivity launches and you can get the intent by calling getIntent() anywhere in activity lifecycle. but because you are setting singleTop flag on activity if HomePageTabActivity is already launched, Android will not launch it again and will pass the new Intent (provided in notification) to onNewIntent() instead. you can consume it there or even call the getIntent() to get the new value from there on.
Receive messages in an Android app. Messages with both notification and data payload, both background and foreground. In this case the data payload is delivered to extras of the intent of your launcher activity. If you want to get it on some other activity, you have to define click_action on the data payload. So get the intent extra in your launcher activity.

Background Service with Notification

I am developing an Android application which calls API's to fetch data. Now I want to perform this task in background and each time data is changed in the List view, a notification should be generated.
How can I achieve this?
How can I make my API called in background and how can i generate notification.
I am new to Services and BroadcastReceivers so help me
I am calling the service this way:
startService(new Intent(this, MyService.class).putExtra("Background",true));
I created this code to testing purpose. To check if notifications can be called in background even if the app is closed.
My Service Class
public class MyService extends Service {
private Boolean isShowingNotification = true ;
NotificationManager notificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent.hasExtra("Background")) {
if (isShowingNotification) {
StopImportantJob();
stopSelf();
} else
DoImportantJob();
} else {
DisplayNotification("Now showing the demo");
}
return START_NOT_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Toast.makeText(this, "On Create Called", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
super.onDestroy();
notificationManager.cancelAll();
}
public void DisplayNotification(String message){
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setContentTitle(message)
.setContentText("Touch to off Service")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
notificationManager.notify(0,notification);
}
public void DoImportantJob(){
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(1992, notification);
isShowingNotification =true;
}
public void StopImportantJob(){
stopForeground(true);
isShowingNotification = false;
if(false){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){
stopForeground(STOP_FOREGROUND_DETACH);
stopForeground(STOP_FOREGROUND_REMOVE);
}
}
}
}
What I believe I should do is listed below, please correct me if I am wrong.
Start Service in the onCreate() of the MainAcitivity of Application.
In the Service call I will create a method which will do the API call.
On notifyDataSetChanged(); will call the Notification method.
Now here is the question: In Service class the API method will be called in onCreate() or onStartCommand().
Now i want to perform this task in background and each time data is
changed in the List view, a notification should be generated. How can
i achieve this? How can i make my API called in background and how can
i generate notification.
First Decide, whether you want this operation when your application is in Foreground OR Background. Now, if Foreground, you might not want to use Service class and use AsyncTask instead for making your webservice calls and generate the notification and updatethe listview once task is done. If Background, you can create IntentService and do your API operation there. However, in background mode, your application do not need to be notified as your app will not be visible to client.

IntentService not working

I am building an application whereby the notification will ring at a specific time and after which disappear if it is left unattended for 15 minutes. It works when i plug in my device and runs the code. However, once i unplug my device and runs the app, the notification works but it does not disappear after 15 minutes if it is left unattended. Please advice me how should i run the app like how it does when the device is plug into the computer. Also, it should work when the app is killed.
FYI, i'm using notification, alarmmanager, broadcast receiver and intentservice. Below is the snippet of my codes.
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Notification(context, "Wifi Connection On");
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
public void Notification(final Context context, String message) {
// notification codes
}
}
BackgroundService.java
public class BackgroundService extends IntentService {
public BackgroundService() {
super("BackgroundService");
}
#Override
protected void onHandleIntent(Intent intent) {
//countdown 15 minutes and cancel notification automatically
Timer timer=new Timer();
TimerTask task=new TimerTask() {
#Override
public void run() {
// Create Notification Manager
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Dismiss Notification
notificationmanager.cancelAll();
}
};
timer.schedule(task, 900000);
}
}
Manifest.xml
<receiver android:name=".AlarmReceiver" android:process=":remote" />
<service android:name=".BackgroundService" />
Please provide me some suggestions. Thank you.
This service will run twice: first time it does nothing except rescheduling, second time it cancels notifications.
public class BackgroundService extends IntentService {
private static final int REQUEST_CODE = 42;
private static final String ACTION_CANCEL_NOTIFS = "CancelNotifications";
public BackgroundService() {
super("BackgroundService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null && ACTION_CANCEL_NOTIFS.equals(intent.getAction())) {
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationmanager.cancelAll();
}
else {
reschedule();
}
}
private void reschedule() {
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, 15);
final Intent serviceIntent = new Intent(this, getClass());
serviceIntent.setAction(ACTION_CANCEL_NOTIFS);
PendingIntent pendingIntent = PendingIntent.getService(this, REQUEST_CODE, serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
Explanation:
In your code, I assume, you start your service with startService(new Intent(this, BackgroundService.class)). This intent is passed as a parameter in onHandleIntent(Intent), which means you can access it from inside your service.
Intent allows you to pass additional data, such as action (useful for IntentFilters) or extras. Because you haven't set any, the first time around the execution goes to the else branch of onHandleIntent() method. AlarmManager is then scheduled to run your service in 15 minutes with serviceIntent. Note serviceIntent.setAction(ACTION_CANCEL_NOTIFS). So the second time around the execution goes to the if branch and cancels notifications.
A better approach would be creating a pending intent right from inside your activity instead of starting a service with startService. That would make your service simpler and more cohesive.
Service only runs when CPU is awake. If CPU gets off, service will not run.
SO to make your service to be run if phone goes to sleep, you need to aquire wake lock.
BackgroundService class
public class BackgroundService extends IntentService {
private PowerManager.WakeLock wl;
public BackgroundService() {
super("BackgroundService");
}
#Override
protected void onHandleIntent(Intent intent) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Partial lock permission");
wl.acquire();
//countdown 15 minutes and cancel notification automatically
Timer timer=new Timer();
TimerTask task=new TimerTask() {
#Override
public void run() {
// Create Notification Manager
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Dismiss Notification
notificationmanager.cancelAll();
wl.release();
}
};
timer.schedule(task, 900000);
}
}
If this does work out, try to give below permission in Android Manifest file
<uses-permission android:name="android.permission.WAKE_LOCK" />

Keep broadcast receiver running after application is closed

I need to keep broadcast receiver running all the time after app has been started.
Here is the code that registers this receiver in the application
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenEventsReceiver();
registerReceiver(mReceiver, filter);
And code for receiver
public class ScreenEventsReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
wasScreenOn = false;
Log.d("ScreenEventReceiver", "ON");
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
wasScreenOn = true;
Log.d("ScreenEventReceiver", "ON");
}
}
}
You can use a service
In main app start/stop the service
Intent service = new Intent(context, MyService.class);
context.startService(service);
...
Intent service = new Intent(context, MyService.class);
context.stopService(service);
service
public class MyService extends Service
{
private static BroadcastReceiver m_ScreenOffReceiver;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
registerScreenOffReceiver();
}
#Override
public void onDestroy()
{
unregisterReceiver(m_ScreenOffReceiver);
m_ScreenOffReceiver = null;
}
private void registerScreenOffReceiver()
{
m_ScreenOffReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "ACTION_SCREEN_OFF");
// do something, e.g. send Intent to main app
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(m_ScreenOffReceiver, filter);
}
}
Accepted answer is not an actual answer i think. I will explain what the issue. I think you are testing your app in the Huawie, Oppo, Vivo, Xiomi,asus....... or some devices. With that devices if we close the application they will also close our broadcast receivers. So thats the problem.(To check that use a with pixel nexus emulator). I will explain how to resolve this.``
we would add our app to the protected app list. OS only allow to them to continue broadcast receiver activities.(Copy this array declaration to your code)
private static final Intent[] POWERMANAGER_INTENTS = {
new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
new Intent().setComponent(new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
new Intent().setComponent(new ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity"))};
Put these code to your onCreate Method. Here i used shared preference for check it only first time of the app open.
`
final SharedPreferences.Editor pref = getSharedPreferences("allow_notify", MODE_PRIVATE).edit(); pref.apply(); final SharedPreferences sp = getSharedPreferences("allow_notify", MODE_PRIVATE)`;
if(!sp.getBoolean("protected",false)) {
for (final Intent intent : POWERMANAGER_INTENTS)
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Alert Title").setMessage("Alert Body")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(intent);
sp.edit().putBoolean("protected",true).apply();
}
})
.setCancelable(false)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create().show();
break;
Be careful if you are using Android 4.4.x as there is a bug which kills background services when closing the app. I was testing my app in Android 4.4.2 and I had the same problem. Here there is a detailed explanation:
http://www.androidpolice.com/2014/03/07/bug-watch-stopping-apps-on-android-4-4-2-can-silently-kill-related-background-services-a-fix-is-on-the-way/
You cannot receive some broadcast events through components declared in manifest.
These events are
ACTION_BATTERY_CHANGED
ACTION_CONFIGURATION_CHANGED
ACTION_SCREEN_OFF (You are playing with this event)
ACTION_SCREEN_ON (You are playing with this event)
ACTION_TIME_TICK
Reference https://developer.android.com/reference/android/content/Intent.html#ACTION_SCREEN_ON
So in your specific events,
you will have to create a Service & you will have to register your event explicitly in service onCreate() with with Context.registerReceiver().
For other events,
entry in manifest is sufficient.
If you declare BroadcastReceiver in the Manifest, it will always be active and be called even if the application is closed/stopped
You could start a service that is running in the foreground. That's the only way to ensure (mostly) that your app will get the events. There is still a chance that your foreground service could get killed in times of crazy memory pressure from the OS (so it's not foolproof). If you start a service in the foreground, the user will see a persistent notification to know that it is always running, though.
So the moral of the story is, do you really need to monitor the screen off/on events at all times? The reason that they force you to register a receiver not in the manifest is that they don't want people to always be monitoring these events and slowing down the device. What are you trying to accomplish?
The best way I found is the Foreground Services. I registered my BroadcastReceiver from my Service only under the onStartCommand() as I want my service needs to run always, I returned START_STICKY
This way, my broadcast receiver survives even after terminating the app from stack.
Used below code in my service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("rht", "Received start id " + startId + ": " + intent);
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
This is how I started my service
Intent serviceIntent = new Intent(this, SpeechServiceForeground.class);
ContextCompat.startForegroundService(this, serviceIntent);

Categories

Resources