How to clear the notification when the app is force closed? - java

Am Working on a timer based app where the notification shows up when the timer starts to run. I have set it as ongoing so that it cannot be cleared.
I have used cancelAll() method for some cases which works fine but when I force close the app, the notification still shows up and cannot be removed and tried to use the method in onDestroy() method still the problem prevails.
Here is my code and created the channel in another class :
public void sendNotif(){
Intent resultIntent = new Intent(this, TimerActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
not = new NotificationCompat.Builder(this,Notif.CHANNEL_ID)
.setSmallIcon(R.drawable.curved_shape)
.setContentTitle("Productivity Timer")
.setContentText("Your Timer is Running")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
notificationManager.notify(1,not);
}

I found this great solution once, I will retype it here
Since your application and the notification are handled in different threads, so killing your application won't kill the notification. The solution is to create a Service to kill notification, since services will restart themselves when the app is killed suddenly, you can use the automatic restart to kill the notification.
Create the service class
public class KillNotificationsService extends Service {
public class KillBinder extends Binder {
public final Service service;
public KillBinder(Service service) {
this.service = service;
}
}
public static int NOTIFICATION_ID = 666;
private NotificationManager mNM;
private final IBinder mBinder = new KillBinder(this);
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNM.cancel(NOTIFICATION_ID);
}
}
Add it to your manifest
<service android:name="KillNotificationsService"></service>
Always create the Service before fireing the notification, and use the static notificationid
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder binder) {
((KillBinder) binder).service.startService(new Intent(
MainActivity.this, KillNotificationsService.class));
Notification notification = new Notification(
R.drawable.ic_launcher, "Text",
System.currentTimeMillis());
Intent notificationIntent = new Intent(MainActivity.this,
Place.class);
PendingIntent contentIntent = PendingIntent.getActivity(
MainActivity.this, 0, notificationIntent, 0);
notification.setLatestEventInfo(getApplicationContext(),
"Text", "Text", contentIntent);
NotificationManager mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNM.notify(KillNotificationsService.NOTIFICATION_ID,
notification);
}
public void onServiceDisconnected(ComponentName className) {
}
};
bindService(new Intent(MainActivity.this,
KillNotificationsService.class), mConnection,
Context.BIND_AUTO_CREATE);

Related

How can I make the button pause remember where the MediaPlayer stopped?

I made a MediaPlayer some time ago and I faced a big issue. The audio can't be played in the background so I must use Service. At this point, I managed to play the music and to stop it, but when I click play again, it restarts and I don't know what to do. I am new to coding. Other than that I want to make a working seekbar and a textView for player position, but that for another time. If there is someone to help me I would really appreciate it.
Here is the code I am using now:
btPause = findViewById(R.id.btPauseMusic);
btPlay = findViewById(R.id.btPlayMusic);
btPlay.setOnClickListener(v -> {
startService(new Intent(this, BackgroundMusicService.class));
btPlay.setVisibility(View.GONE);
btPause.setVisibility(View.VISIBLE);
});
btPause.setOnClickListener(v -> {
stopService(new Intent(this, BackgroundMusicService.class));
btPause.setVisibility(View.GONE);
btPlay.setVisibility(View.VISIBLE);
});
}
The service:
public class BackgroundMusicService extends Service {
private MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer = MediaPlayer.create(this, R.raw.ding_dong);
mediaPlayer.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
}
}
Add this notification code in your BackgroundMusicService inside on onCreate.
Intent stopSelf = new Intent(this, BackgroundMusicService.class);
stopSelf.setAction("Stop");
PendingIntent pStopSelf = PendingIntent
.getService(this, 0, stopSelf
, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification;
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(
0, "Pause", pStopSelf
).build();
Intent startSelf = new Intent(this, BackgroundMusicService.class);
stopSelf.setAction("Start");
PendingIntent pstartSelf = PendingIntent
.getService(this, 0, stopSelf
, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notifications;
NotificationCompat.Action actions =
new NotificationCompat.Action.Builder(
0, "Play", pstartSelf
).build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel("channal", "Notification", NotificationManager.IMPORTANCE_HIGH);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(serviceChannel);
notification = new NotificationCompat.Builder(this, "channal")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("Music.")
.setPriority(Notification.PRIORITY_MAX)
.addAction(action)
.addAction(actions).build();
} else {
notification = new NotificationCompat.Builder(this, "channal")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("App name")
.setContentText("Music.")
.setPriority(Notification.PRIORITY_MAX)
.addAction(action)
.addAction(actions)
.build();
}
NotificationManager notificationManager =
(NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
startForeground(1, notification);
In onStartCommand your intent actions are called where you can pause and play the music by using the length.
int length=0;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if ("STOP".equals(intent.getAction())) {
//inside here pause the music.
mediaPlayer.pause();
length = mediaPlayer.getCurrentPosition();
}else if ("Start".equals(intent.getAction())) {
//inside here play the music with seekto by length where the music was.
mediaPlayer.start();
mediaPlayer.seekTo(length);
}
return START_STICKY;
}
Note: If you still did not understand anything you can ask me in the comment.

Is there a way to make my foreground service run without stopping. It stops when phone cache is cleared by Cross(X) button in minimize window?

I have made a foreground service and it runs non-stop but stops only when the phone cache is cleared (Clicking on Cross(X) button in the Recent Apps window ). Is there a way I can run it non-stop even after clearing the recent apps? And yes, there are other applications which run non-stop in this situation also, like Google Music.
I have tried overriding the Service onDestroy(), onTrimMemory(), dump() methods.
public class MyForeGroundService extends Service {
String CHANNEL_ID = "My Service";
#Override
public void onCreate() {
createNotificationChannel();
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("Title")
.setContentText("Content Text")
.setPriority(NotificationCompat.PRIORITY_MAX)
.build();
startForeground(1, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "Audio Capture Started !", Toast.LENGTH_LONG).show();
return START_REDELIVER_INTENT;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
Log.i(TAG, "createNotificationChannel()");
}
#Override
public void onDestroy() {
startService(new Intent(getApplicationContext(), MyForeGroundService.class));
Intent intent = new Intent(getApplicationContext(), MyForeGroundService.class);
sendBroadcast(intent);
Toast.makeText(getApplicationContext(), "Service Killed!!!", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent intent = new Intent(getApplicationContext(), MyForeGroundService.class);
startService(intent);
}
#Override
public void onTrimMemory(int level) {
startService(new Intent(getApplicationContext(), MyForeGroundService.class););
}
#Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
startService(new Intent(getApplicationContext(), MyForeGroundService.class););
}
But stops only when the phone cache is cleared (Clicking on Cross(X)
button in the Recent Apps window )
You mean when the app removed from recent apps.
There are other application which run non-stop in this situation also.
They using their own hacks.
Is there a way to make my foreground service run without stopping?
No, you should have your own implementation to do so.

Android Service stops broadcasting progress after a while

I have an Activity where the user can download a video. Upon user's click, the Download Service starts to download the content.
There is a progress bar in the Activity UI which I would like to update according to download progress in the service which broadcasts the progress periodically.
Everything works fine but after a certain time the service stops sending any broadcast progress, hence, the UI does not update anymore.
Additionally, how I can resume receiving the progress broadcast when the user goes to another Activity and comes back to this Activity? I mean, even if the above issue is solved, when the user presses back button and go to other activity and comes back to this activity, the progress gets lots. How can I check for any existing broadcast and receive it whenever the user comes to this activity.
In the ACTIVITY:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Log.d("DownloadService", "Progress Received In Activity");
Double progress = bundle.getDouble("PROGRESS");
updateDownloadProgressBar(progress);
}
}
};
private void startDownloadService() {
final String videoId = mItem.getAttributes().get(KEY_ASSET_ID);
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("VIDEOID", videoId);
startService(intent);
}
in the onResume():
registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION_SERVICE));
in the onPause():
unregisterReceiver(receiver);
In the SERVICE:
private void publishProgress(double progress) {
Log.d(TAG, "Broadcasting progress from Service");
Intent intent = new Intent(NOTIFICATION_SERVICE);
intent.putExtra("PROGRESS", progress);
sendBroadcast(intent);
}
The download and progress work fine to 38% then stop.
It seems that the service is being stopped/killed from the OS, to avoid that use foreground service so you can make sure it will not be killed from the OS.
See the sample code below:
Service
public class PendingService extends Service {
private final static String TAG = "PendingService";
public final static int NOTIFICATION_ID = 94;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startInForeground();
// Do your work here ...
return START_STICKY;
}
private void startInForeground() {
String NOTIFICATION_CHANNEL_ID = "default";
String NOTIFICATION_CHANNEL_NAME = "My Pending Service";
String NOTIFICATION_CHANNEL_DESC = "This notification holding a pending task";
Intent notificationIntent = new Intent(this, SplashActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.notification)
.setOngoing(true)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setDescription(NOTIFICATION_CHANNEL_DESC);
channel.setSound(null, null);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
Notification notification = builder.build();
startForeground(NOTIFICATION_ID, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
removeNotification(NOTIFICATION_ID);
// ....
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void removeNotification(int notificationId) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.cancel(notificationId);
}
}
}
Utils you may need
class ServiceUtils {
/**
* #param service: Service to run
*/
fun startService(context: Context, service: Class<out Service>) {
val serviceIntent = Intent(context, service)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent)
} else {
context.startService(serviceIntent)
}
}
/**
* #return True: if the service is running
*/
fun isServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
}

Getting Website Data From Running Service [duplicate]

I understand that a Service class runs in the background in Android and I also understand how to start and stop a service.
I am just trying to get a better idea of how to use a Service.
So say I have a service running in the background. How can I simply get the URL name of a webpage from a web browser app.
Her is my service below:
public class MyService extends Service {
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do your jobs here
startForeground();
return super.onStartCommand(intent, flags, startId);
}
private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // Create a Notification Channel
.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(getString(R.string.runningtitle))
.setContentText(getString(R.string.runningtext))
.setContentIntent(pendingIntent)
.build());
}
}

Broadcast receiver never receives intent

I have a problem with receiving notification. I am sure it is sent as I see log for sending. But I never receive it as I never see log or notification. I am not quiet sure what I am doing wrong.
And I don't want repeating alarm.
Using Nexus 7 on Marshmallow.
PracticeWordsActivity.java
public void setAlarm(int day){
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmIntent = new Intent(PracticeWordsActivity.this,AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
//alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis()+15000, pendingIntent);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+15000, pendingIntent);
Log.e(TAG,"Lift off");
}
AlarmService
public class AlarmService extends IntentService
{
private static final int NOTIFICATION_ID = 1;
private static final String TAG = "AlarmService";
private NotificationManager notificationManager;
private PendingIntent pendingIntent;
public AlarmService() {
super("AlarmService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e(TAG,"Alarm Service has started.");
Context context = this.getApplicationContext();
notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this,MainActivity.class);
Bundle bundle = new Bundle();
bundle.putString("test", "test");
mIntent.putExtras(bundle);
pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Resources res = this.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
.setTicker("TITLE")
.setAutoCancel(true)
.setContentTitle("TITLE2")
.setContentText("SUBJECT");
notificationManager =(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, builder.build());
Log.e(TAG,"Notifications sent.");
}
AlarmReceiver.java
public class AlarmReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "AlarmReceiver";
Intent intent;
PendingIntent pendingIntent;
NotificationManager notificationManager;
#Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "BroadcastReceiver has received alarm intent.");
Intent service1 = new Intent(context, AlarmService.class);
context.startService(service1);
}
}
AndroidManifest.xml
I have set receiver and service after declaring last activity in AndroidManifest.
...
</activity>
<receiver android:name=".AlarmReceiver"
android:enabled="true"/>
<service android:name=".AlarmService" />
</application>
You're using AlarmManager.ELAPSED_REALTIME_WAKEUP to set the alarm. ELAPSED_REALTIME_WAKEUP means time elapsed since the device booted up.
If you want the alarm to be triggered 15 seconds after you set it, use:
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+15000, pendingIntent);
or
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+15000, pendingIntent);
Also, I see you're triggering the alarm in WAKEUP mode and in your broadcast receiver you're starting a service. There is a chance that the device will go back to sleep before the service gets started. You can use WakefulBroadcastReceiver to prevent that.
You don't need to worry about repeating alarms, if you use the same intent to set a new alarm, the previous alarm that is using the same intent will be canceled.

Categories