Android service doesn't send notifications on app exit - android

I have created a background service that checks for value changes in my Firebase Database and sends a Notification if there are any changes. The service notifies for value changes as long as the app is running. When I close the app, I stop receiving notifications. My onStartCommand contains a new thread comprising of a firebase value event listener. As the value changes
I call sendNotification method. Here's my complete service class:
public class NotifyService extends Service
{
Firebase mRef;
#Override
public IBinder onBind(Intent p1)
{
// TODO: Implement this method
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Toast.makeText(this,"service started",Toast.LENGTH_LONG).show();
Firebase.setAndroidContext(this);
mRef= new Firebase(myURL);
Runnable run = new Runnable(){
#Override
public void run(){
mRef.child("politics").child("story1").child("title").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot p1)
{
// TODO: Implement this method
String data = (String)p1.getValue();
sendNotification(data);
}
#Override
public void onCancelled(FirebaseError p1)
{
// TODO: Implement this method
}
});
mRef.child("sports").child("story1").child("title").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot p1)
{
// TODO: Implement this method
String data = (String)p1.getValue();
sendNotification(data);
}
#Override
public void onCancelled(FirebaseError p1)
{
// TODO: Implement this method
}
});
mRef.child("science").child("story1").child("title").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot p1)
{
// TODO: Implement this method
String data = (String)p1.getValue();
sendNotification(data);
}
#Override
public void onCancelled(FirebaseError p1)
{
// TODO: Implement this method
}
});
mRef.child("gossip").child("story1").child("title").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot p1)
{
// TODO: Implement this method
String data = (String)p1.getValue();
sendNotification(data);
}
#Override
public void onCancelled(FirebaseError p1)
{
// TODO: Implement this method
}
});
}};
Thread serviceThread = new Thread(run);
serviceThread.start();
return Service.START_STICKY;
}
#Override
public void onDestroy()
{
Toast.makeText(this, "activity destroyed", Toast.LENGTH_LONG).show();
}
public void sendNotification(String title){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(NotifyService.this);
mBuilder.setSmallIcon(R.drawable.nicon);
mBuilder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.nlicon));
mBuilder.setAutoCancel(true);
mBuilder.setContentTitle("New Story")
.setContentText(title);
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(NotifyService.this);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify((int)System.currentTimeMillis(), mBuilder.build());
}
}
I call it with
Intent i = new Intent(this, NotifyService.class);
startService(i);
What is it that doesn't let the notifications appear after app exit. I suspect it is something wrong with the notification method.

My service was apparently running in settings, but it was actually getting killed after the app was killed.
To keep your service running, instead of
startService(new Intent(this, MyService.class));
use this:
Intent serviceintent =new Intent(this, MyService.class);
PendingIntent pendingintent =PendingIntent.getService(this,0, serviceintent,0);
AlarmManager alarm =(AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingintent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5000, pendingintent);
This ensures your service keeps using AlarmManager every 5 seconds, so no matter what happens, the service will keep running.

Related

how show notification in onTaskComplete from this code when app closed or runnig in background

this code get request from server and do some thing. i want when app is closed get request and show it by notification. i can get message from firebase and show it but this is not something that i want
MyActivity
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;
public class MyActivity extends ActionBarActivitiy implements AsyncTaskCompleteListener{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
.
.
.
}
private void displayFirebaseRegId() {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
String regId = preferenceHelper.getSessionToken();
if (!TextUtils.isEmpty(regId))
}
private void subscribeToPushService() {
FirebaseMessaging.getInstance().subscribeToTopic("news");
String token = FirebaseInstanceId.getInstance().getToken();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
#Override
protected void onDestroy() {
}
#Override
public void onTaskCompleted(String response, int service) {
super.onTaskCompleted(response, service);
switch (service) {
case MyValues.Service.REQUEST_NEW:
// addNotification();
...
if (requestId == MyValues.NO_REQUEST) {
addNotification();
addNewFragment(new myFragment(), false,
MyValues.REQUEST_, true);
} else {
...
}
break;
}
}
ActionBarActivitiy
abstract public class ActionBarActivitiy extends AppCompatActivity implements OnClickListener , AsyncTaskCompleteListener
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
public void addNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(MyApplication.applicationContext)
.setSmallIcon(R.mipmap.ic_cl)
.setContentTitle("Notifications get request")
.setContentText("This is get request notification");
Intent notificationIntent = new Intent(MyApplication.applicationContext, MainActivity.class);
PendingIntent contentIntent =
PendingIntent.getActivity(MyApplication.applicationContext, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
builder.setSound(Uri.parse("android.resource://"
+ MyApplication.applicationContext.getPackageName() + "/" + R.raw.sfx_counter_loop));
// builder.setOngoing(true);
try {
builder.setWhen(System.currentTimeMillis());
builder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
builder.setLights(Color.RED, 3000, 3000);
}catch (Exception e){
}
// Add as notification
NotificationManager manager = (NotificationManager)
MyApplication.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
#Override
public void onTaskCompleted(String response, int service) {
}
....
}
interface AsyncTaskCompleteListener
public interface AsyncTaskCompleteListener
{
void onTaskCompleted(String response, int service);
}
You can use A service, An alarm manager to do so.
Schedule a timer tat will run the service. The service will fetch the data and then show the notification. You can also use IntentService for that so as to free up your main thread.
Edit
Here is an link for alarm manager :
https://developer.android.com/training/scheduling/alarms.html
and IntentService :
https://developer.android.com/training/run-background-service/create-service.html
Also, to call certain task before your app gets close, call your method in onStop right before calling super.

The same push notification keeps appearing whenever i open my apps

The same push notification keeps appearing whenever I reopen my apps although i have already cleared the notification in the notification bar. Secondly how do I implement a service so that my apps can receive notification although the apps is closed.
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPreferences = getSharedPreferences(Constants.SHARED_PREF, MODE_PRIVATE);
String id = sharedPreferences.getString(Constants.UNIQUE_ID, null);
Firebase firebase = new Firebase(Constants.FIREBASE_APP + id);
firebase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
String msg = snapshot.child("msg").getValue().toString();
if (msg.equals("none"))
return;
showNotification(msg);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: ", firebaseError.getMessage());
}
});
return START_STICKY;
}
private void showNotification(String msg){
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
Intent intent = new Intent(NotificationListener.this,ViewRecord.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pendingIntent);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(alarmSound);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("Notifier");
builder.setContentText(msg);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
builder.setAutoCancel(true);
notificationManager.notify(1, builder.build());
}
my service code as below. and i call the service at onCreate function in the 1st activity..
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// For time consuming an long tasks you can launch a new thread here...
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
}
}
Posting this as answer since code in comment wud make it look unstructured
isServiceStarted
public class MainActivity extends AppCompatActivity {
private SharedPreferences servicePref;
private boolean isServiceStarted;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
servicePref = getSharedPreferences("servicePref", MODE_PRIVATE);
isServiceStarted = servicePref.getBoolean("isServiceStarted", false);
if (!isServiceStarted) {
startService(new Intent(this, MyService.class));
servicePref.edit().putBoolean("isServiceStarted",true).apply();
}
}
and in ur MyService.class inside onStop method do this without fail.
public class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
// save value as false when service gets destroyed so as to start again when u open the app
getSharedPreferences("servicePref", MODE_PRIVATE).edit().putBoolean("isServiceStarted",false).apply();
}
}
override the onStartCommand() method and then return START_STICKY.

Android notification keeps reappearing

I am trying to get a better handle on notifications with the simple app shown below (at least the relevant parts). I would like to show a notification icon when the app is not destroyed, and remove the notification icon when it is destroyed; pretty simple right?
My problem is that when the fragment's onDestroyView event is fired the notification icon does disappear, but then reappears and I can't figure out why.
To try to figure things out a bit better I create a stop notification button that calls the mServiceBinder's stop() method, which does remove the notification icon for good even though it is calling the same method called in the onDestroyView event.
Any ideas to what the problem is?
MainActivityFragment
package org.chrisolsen.notificationtest;
import ...
/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
private ServiceConnection mServiceConn;
private TestService.TestBinder mServiceBinder;
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onDestroyView() {
Log.d("Fragment", "onDestroyView");
// *try* to prevent services from restarting
if (mServiceConn != null) {
getActivity().unbindService(mServiceConn);
}
if (mServiceBinder != null) {
mServiceBinder.stop();
}
mServiceConn = null;
mServiceBinder = null;
super.onDestroyView();
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
Log.d("Fragment", "onViewCreated");
Button showButton = (Button) view.findViewById(R.id.button);
Button hideButton = (Button) view.findViewById(R.id.btnHide);
showButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Fragment", "onCLick");
mServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("serviceConn", "onConnected");
mServiceBinder = (TestService.TestBinder) service;
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("serviceConn", "onDisconnected");
}
};
Intent service = new Intent(getActivity(), TestService.class);
getActivity().startService(service);
getActivity().bindService(service, mServiceConn, Context.BIND_ABOVE_CLIENT);
}
});
hideButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
mServiceBinder.stop();
}
});
}
}
TestService
package org.chrisolsen.notificationtest;
import ...
public class TestService extends Service {
public class TestBinder extends Binder {
public void stop() {
TestService.this.stopForeground(true);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("TestSErvice", "onDestroy");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return new TestBinder();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TestSErvice", "onHandleIntent");
Context c = getApplicationContext();
Intent activityIntent = new Intent(c, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
c, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("The Content Text")
.setOngoing(false)
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_LOW)
.setContentTitle("The content title");
startForeground(1, builder.build());
return super.onStartCommand(intent, flags, startId);
}
}
The notification reappears because your service onStartCommand called after your activity closed.
It is a bad place to create and show notification. onStartCommand method maybe called multiple times. Place the notification creation to the onCreate for example.
What do you mean when you wrote "app is not destroyed"? If you thought while your service is running, put the creation to the onCreate and remove it in onDestroy.
Returning START_STICKY instead of super.onStartCommand(intent, flags, startId), is what I should've been doing.

How to invoke an activity from background services when arrives a notification?

I want to check notifications from background receivers or services.
The notification is shown, but it should also invoke an activity.
MainActicityClass
Here I have created the alarm class which would call broadcast manager at specific interval
public class MainActivity extends AppCompatActivity {
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.context = this;
Intent alarm = new Intent(this.context, AlarmReceiver.class);
boolean alarmRunning = (PendingIntent.getBroadcast(this.context, 0, alarm, PendingIntent.FLAG_NO_CREATE) != null);
if(alarmRunning == false) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.context, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 60000, pendingIntent);
}
}
Alarm Receiver Class
This is the broadcast class to invoke from back ground
public class AlarmReceiver extends BroadcastReceiver {
public AlarmReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Intent background = new Intent(context, MyListenerServices.class);
context.startService(background);
}
}
MyListener
This is subclass of notificationlistener services
Its reads any incoming notification but unable to read the notification from inactive class
Integrate class read any kind of incoming notification from background
public class MyListenerServices extends NotificationListenerService{
public MyListenerServices() {
}
private boolean isRunning;
private Context context;
private Thread backgroundThread;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
this.context = this;
this.isRunning = false;
this.backgroundThread = new Thread(myTask);
}
private Runnable myTask = new Runnable() {
public void run() {
// Do something here
Log.d("MSG", "ServiceRunning");
StatusBarNotification[] statusBarNotifications = getActiveNotifications();
Log.d("MSG", "New Object2 "+statusBarNotificationsArray);
if (statusBarNotifications.length > 0) {
Log.d("MSG", "New Object "+statusBarNotifications.length);
//
Intent i = new Intent(context, AutomaticCameraActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
// }
// }catch (Exception e){
// Log.d("MSG",e.getMessage());
}
stopSelf();
}
};
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
Notification mNotification=sbn.getNotification();
Log.v("MSG"," Notification"+ mNotification);
}
#Override
public void onDestroy() {
this.isRunning = false;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!this.isRunning) {
this.isRunning = true;
this.backgroundThread.start();
}
return START_STICKY;
}
}
Any help would be appreciated
Thanks in advance
Create a pending intent
Intent resultIntent = new Intent(this, ResultActivity.class);
//Change ResultActivity by your activity you want invoke
...
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
More information in Create Notification

Service and Chronometer Synchronization

I need to be able to start chronometer, then close activity, after that through notifications, back to that activity, and see the right time in chronometer.
What I've Done
A part of my Activity:
public void doClick(View target)
{
switch(target.getId())
{
case R.id.buttonStart:
{
Mchronometer.setBase(SystemClock.elapsedRealtime());
Mchronometer.start();
Intent intent = new Intent(RecentActivity.this, ChronometerService.class);
intent.putExtra("task_name",task_name);
intent.putExtra("task_id",task_id);
intent.putExtra("ellapsedTime",Mchronometer.getBase());
Log.d("base",""+Mchronometer.getBase());
startService(intent);
break;
}
case R.id.buttonStop:
{
stopService(new Intent(RecentActivity.this, ChronometerService.class));
Mchronometer.stop();
Mchronometer.setBase(SystemClock.elapsedRealtime());
break;
}
case R.id.button3:
{
break;
}
}
}
A part of my Service:
public class ChronometerService extends Service {
private ThreadGroup myThreads = new ThreadGroup("ServiceWorker");
private NotificationManager notificationMgr;
private int task_id;
private long ellapsedTime;
#Override
public void onCreate() {
super.onCreate();
notificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
String task_name =intent.getExtras().getString("task_name");
task_id =intent.getExtras().getInt("task_id");
ellapsedTime = intent.getExtras().getLong("ellapsedTime");
Log.d("servicebase",""+ellapsedTime);
displayNotificationMessage(task_name);
new Thread(myThreads, new ServiceWorker(),"ChronometerService").start();
return START_STICKY;
}
private class ServiceWorker implements Runnable {
public void run() {
}
}
#Override
public void onDestroy()
{
myThreads.interrupt();
notificationMgr.cancelAll();
super.onDestroy();
}
public IBinder onBind(Intent intent) {
return null;
}
public void displayNotificationMessage(String message){
Notification notification = new Notification(R.drawable.emo_im_winking,message,System.currentTimeMillis());
notification.flags = Notification.FLAG_NO_CLEAR;
Intent intent = new Intent(this, RecentActivity.class);
intent.putExtra("task_id", task_id);
intent.putExtra("ellapsedTime",ellapsedTime);
Log.d("servicebase1",""+Long.toString(ellapsedTime));
PendingIntent contentintent = PendingIntent.getActivity(this,0,intent,0);
notification.setLatestEventInfo(this,"ChronometerService",message,contentintent);
notificationMgr.notify(0, notification);
}
}
I tried to send a message from activity to a service, which contains elapsed information.
If I started it first on my device (after system load) it's works right, but when I launch it again. The activity receives wrong message. It receives the time of the first service launched on the device.
As you can see I also send one more variable, and activity reads it correctly.
I've found a solution to my question.
It's simple.
It's needed to use flag(PendingIntent.FLAG_UPDATE_CURRENT)
PendingIntent contentintent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
And it's work fine.

Categories

Resources