I have this Runnable method which send a notification once it is called and every minute sends a JSON Post on an HTTP Server. So i coded the method "sendNotification" to keep informed the user regards the "service" is running but when I close the app, the method to send the JSON stops and the notification stays active on the notification bar. I would like to close the notification as well.
//Runnable methods for frequency position
private final Runnable oneMinuteRunnable = new Runnable() {
#Override
public void run() {
sendNotification();
getTimestamp();
new Thread(new Runnable() {
#Override
public void run() {
getLocation();
doPostRequest();
}
}).start();
handler.postDelayed(this, 60 * 1000);
}
};
This is the notification method
//Make notification when the frequency service is running
public void sendNotification() {
Notification notification = new NotificationCompat.Builder(this, com.example.httptracker.Services.Notification.NOTIFICATION_ID)
.setSmallIcon(R.drawable.ic_baseline_run_circle_24)
.setContentTitle("AMP Tracker")
.setContentText("Tracker is running")
.build();
compat.notify(1, notification);
}
I looked up online and I saw only solutions with a Service class but I would need to develop a "stop service" button to cancel the notification. But it is not what I need. The notification should disappear once the app is closed or the method killed.
Thanks in advance
try to cancel your notification with:
compat.cancel(1); // assuming compat is NotificationManager instance, 1 is your id
in e.g. onDestroy of Activity or any place when your app is stopping oneMinuteRunnable looped execution
Related
From the stackoverflow and many blogs, i surely understand that foreground service never run without notification in API>25. But still i confuse that Is notification mandory while app is running on screen or visible.
For eg. no need of notification when user stand within app. So is this possible to remove notification while app running ?
In service class
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
......
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
startForeground(1, notification);
}
return START_NOT_STICKY;
}
In activity
Intent myService = new Intent(this, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(myService);
} else {
startService(myService);
}
It's not possible to remove the notification while the foreground service is running, but it is possible to change your foreground service back into a "regular" service. This removes the need for a notification. In fact, the function to use,
stopForeground(boolean removeNotification)
...includes a removeNotification parameter just for that purpose. You service can switch from being "foreground" to "regular" on demand, by alternating calls to startForeground() and stopForeground().
In case it's not clear, you'd probably want to call stopForeground() whenever you have at least one Activity in a "started" state. This is something you'd have to track manually. Then, when the number of "started" activities reaches 0, you'd call startForeground().
EDIT
One approach is to use a bound service. Then, it's easy to call stopForeground() on it when you want.
Assume you have a single Activity. You can bind it to the service (see this doc or use one of these examples). Then your onServiceConnected() function could look like this (adapted from the Google example):
//MyActivity.java:
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mService.stopForeground(true); //This makes the notification go away
bound = true;
}
...
#Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (bound) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
mService.startForeground(1, notification); //This brings the notification back! Service is already running, and continues to run.
unbindService(this);
bound = false;
}
}
No, it is mandatory even your app is running in foreground your foreground service need a notification.
You won't able to hide it.
Why :
You can use any other background task handler like intent service, job sclr but things is designed defferent for foreground service your user understand that event i will close this one of it's progress is going to keep running but things is defferent with background service your know it will do something in background but when system decide it's best time to do it not when your app want (as like in foreground service).
One more case ex :
Suppose your app in foreground battery level is lower than expected by user or system your foreground service will execute instantly no matter what so it's important for your user to know this it's running and take my resources (battery, data, etc)
Hopefully you got my mean 🙂
I am tryiny to update my edittext in UI. I have a service from where I send a intent by clicking a button and update in the UI. Everything works fine. But I would like to send intent without button click.
What I tried was to put my Intent in a method and call it oncreate in service but even then it been just called once.
public class myService extends service {
onCreate{
sendMessage();
}
private void sendMessage(){
Intent intent = new Intent("com.example.app.SEND");
intent.putExtra("KEY", (String) Number);
sendBroadcast(intent);
}
When I do like this, I just send empty string which is not useful. And even then just once.
Can I send intent continously ? So that It updates my UI once it receives input ? Any possible way to do it ?
I would like to send intent every 5 seconds.
You can use TimerTask with IntentService for scheduled jobs.
ex:
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
//some execution
}
};
timer.schedule(timerTask, 5000, 5000);
As a Unity3D developer, I've created an application and exported it to Android Studio. My client is asking me to make this app go back to foreground after 10 seconds of user's inactivity (in case the user opens another app). I've tried to create a service that is started on the OnPause function of my UnityPlayerActivity. Then the service would detect the user's inactivity and launch my app again (putting it back to foreground). First I've only tried to use Time.Schedule to launch my app after 10 seconds no matter what, but everytime the application is paused (goes to background), it starts the service and then it crashes. The question is: is there a simple way to do this? I'm not an Android Java Developer (only know the basics) and I'm struggling with this part .
I'm trying to create this Service and then I try to start it from the onPause() function in my activity. When I pause the app on my phone the app crashes. Can anyone tell me if I'm on the right way and, please, help me?
public class ReturnToForeground extends Service {
public ReturnToForeground() {
}
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
Intent intent = new Intent(this, UnityPlayerActivity.class);
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// cancel if already existed
if (mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
return super.onStartCommand(intent, flags, startId);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// do action
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
}
});
}
}
}
Make a timer for when the app is in the onPause(), when the timer reaches 10 seconds you should pass an intent which will make your app active again (let's say taking the user back to the main view). You can save the current data of your app in something like shared preffs, so that information wont be lost in most situations.
In many cases this problem appears when a resource which you are trying to reload is not active anymore inside the application.
From the info you have shared it seems like you are not starting the service correctly. It would be nice if you can add a crash log so that we can debug it and see where is the problem.
Recent changes in Androids background task running behaviour makes it very difficult to keep Services alive and continue work in applications when the phone is locked. My Service is only working properly when the screen is on or the phone gets charged. When the phone is locked, the Service shuts down almost immediately or runs way too slow to be useful in any way.
I tried to use "START_STICKY" flag and a startForeground() Notification to keep the Service alive but this doens't help at all. I'm using a Handler that calls dowork() every 5 seconds, which then checks if theres something to do.
I want to perform a simple task on a certain time event: wake up every half/quarter or full hour, do some quick work without CPU limitation, then shut down until next time. The phone should wake up reliable and accurate on time and get "whitelisted" to use some CPU power for around half a minute. I don't do any intense work, that could affect user performance.
public class MyService extends Service {
public MyService() {
super();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("MyService")
.setContentText("Service is running")
.setPriority(IMPORTANCE_HIGH)
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dowork();
handler.postDelayed(this, 5000);
}
}, 1500);
return START_STICKY;
}
For this question i want to refer to Alarm Manager Example
. This one is doing it's job pretty well, i finally got it working that way.
I'm Developing a simple app that receives the GCM push messages from the PHP server. The App and Server works fine, even with multiple push messages. The only thing I want to add in the app is, If a push message is not received within few seconds, lets say 5seconds, i want my app to Toast a message saying "Network error". I'm using "WakefulBrodcastReceiver" for receiving the push messages. except for this, all code is working fine, as I expect it to.
Working:
Pressing a button notifies the server, that App is ready for receiving the notifications.
Now, i'm having two scenarios,
App haven't received any push message, 5 seconds are passed by since the button press event, SHOW THE TOAST.
I've already received few push messages, 5 seconds are passed by since i've received the last message, SHOW THE TOAST.
following code snippet is written in GCM Handler class, which handles the push messages.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Log.e("HANDLER", "inside run()");
Toast.makeText(mContext, "Network Error", 1000).show();
}
}, Constants.TIME_OUT);
The value of Constants.TIME_OUT is 5000,
the Toast or the Log never displayed.
All I wanted to do was, to show a "Check network connection" message if the app don't receive a Push notification from PHP server in 5 seconds.
as Udi I and Zharf stated, When onHandleIntent returns, the service Shuts down, and so does the delayed runnings. So, I tried the other way.
I used Timer Task.
The code is,
Timer timer;
TimerTask timerTask;
public static void startTimer(Context context) {
timer = new Timer();
initializeTimerTask(context);
timer.schedule(timerTask, 5000); //Time in miliSeconds
}
public static void stopTimer(){
if(timer != null)
timer.cancel();
timer = null;
}
public static void initializeTimerTask(final Context context){
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
Toast.makeText(context, "Check Network connection...", Toast.LENGTH_SHORT).show();
}
}
}
}
}