I have an app (activity). I want it to stay running even if screen goes off, but older solution don't work. As i understand the only solution is to make a service. But is it easy to transform an activity to service?The method with wake lock can't be used any more, as it is deprecated.
Create Foreground Service as below.
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
public class ForegroundService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
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_stat_name)
.setContentIntent(pendingIntent)
.build();
startForeground(1001, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
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);
}
}
}
Dont forget to declarer the service in manifest.
Related
I have created an app that gives the user vibration alerts when tilting the phone in a certain direction. It works fine when running the app, however, when closing the window to run the app in background, the vibration stops working. How can I enable it in background?
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
I also have
<uses-permission android:name="android.permission.VIBRATE"/>
There are several options. One of them is using a a foreground service.
A foreground service is a service that runs in the background and is given higher priority than a background service, which means it is less likely to be killed by the system when the app is closed.
This is a sample code snippet:
public class VibrationForegroundService extends Service {
private Vibrator vibrator;
#Override
public void onCreate() {
super.onCreate();
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1, createNotification());
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
vibrator.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private Notification createNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Vibration Service")
.setContentText("Vibration is running")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true);
return builder.build();
}
}
In addition to #MarcM answer, add "startMyOwnForeground" and it should work with Android 9+
In your fragment:
getActivity().startService(new Intent(getActivity(), VibrationService.class));
VibrationService.java
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.os.Vibrator;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
public class VibrationdService extends Service {
private Vibrator vibrator;
#Override
public void onCreate() {
super.onCreate();
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_vibration)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
vibrator.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private Notification createNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_vibration)
.setContentTitle("Vibration Service")
.setContentText("Vibration is running")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true);
return builder.build();
}
}
I have made an app to test to show a foreground service and then tried to implement it in real app to close wifi after certain time, the code is the same as my test app but it doesn't show notification.
the service works fine but without notification
Main Activity
package com.example.countdownclosewifi.UI;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import com.example.countdownclosewifi.MyService;
import com.example.countdownclosewifi.R;
import com.example.countdownclosewifi.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// Intent filter to set the same action of the broadcast sender
IntentFilter intentFilter_getRemainingTime = new IntentFilter();
intentFilter_getRemainingTime.addAction("Count");
// what will happen when the app receive a broadcast
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int i = intent.getIntExtra("Show", 0);
binding.timeLeft.setText(String.valueOf(i));
}
};
registerReceiver(receiver, intentFilter_getRemainingTime);
binding.start.setOnClickListener(view -> {
if (binding.setTime.getText().toString().isEmpty() || Long.parseLong(binding.setTime.getText().toString()) == 0) {
Toast.makeText(MainActivity.this, "Enter the duration", Toast.LENGTH_SHORT).show();
} else {
Intent serviceIntent = new Intent(this, MyService.class);
int time = Integer.parseInt(binding.setTime.getText().toString());
serviceIntent.putExtra("Time", time);
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){
startForegroundService(serviceIntent);
}
else {
startService(serviceIntent);
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
Service class
package com.example.countdownclosewifi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
//import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.example.countdownclosewifi.UI.MainActivity;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
private WifiManager wifiManager;
private int timeRemaining;
private Timer timer;
// Intent intent;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
IntentFilter intentFilter_stop = new IntentFilter();
intentFilter_stop.addAction("Stop timer");
timeRemaining = intent.getIntExtra("Time", 0);
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (timeRemaining == 0) {
wifiManager.setWifiEnabled(false);
timer.cancel();
stopSelf();
}
setNotification(timeRemaining);
Intent intent = new Intent();
intent.setAction("Count");
intent.putExtra("Show", timeRemaining);
sendBroadcast(intent);
timeRemaining -= 1;
}
}, 0, 1000);
return START_STICKY;
}
public void setNotification(int timeRemaining) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
String channel_id = "id";
Notification notification;
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) {
notification = new Notification.Builder(this, channel_id)
.setContentTitle("You are running out of time")
.setContentText(String.valueOf(timeRemaining))
.setSmallIcon(R.drawable.wifi_24)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.build();
} else {
notification = new NotificationCompat.Builder(this, channel_id)
.setContentTitle("You are running out of time")
.setContentText(String.valueOf(timeRemaining))
.setSmallIcon(R.drawable.wifi_24)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.build();
}
// Notification ID cannot be 0.
startForeground(1, notification);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = "Notification Channel";
CharSequence name = "notification";
NotificationChannel notificationChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.countdownclosewifi">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.CountDownCloseWIFI">
<activity android:name=".UI.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"/>
</application>
</manifest>
it's so clear but i cant see what i am missing to show this notification.
use countdowntimer class instead of timerTask
and set the priority as MAX
NotificationManager.IMPORTANCE_HIGH
I Solved it, the problem was that the Notification ID was not the same as the Channel ID
Why is deleteIntent(PendingIntent) not called when notification is canceled?
I am doing this android tutorial on Notifications and in the 'extra challenge', am using deleteIntent.
However it is not invoked at all. Running in the emulator on API 27.
When I swipe the notification to cancel, the cancelNotification() method is not called.
In the docs, I see the watermark 'deprecated' on the page but it's not in the text.
Not sure if it's actually deprecated or if I am using deleteIntent() wrongly.
https://codelabs.developers.google.com/codelabs/android-training-notifications/#6
In the NotifyMe app, there is one use case in which the state of your
buttons does not match the state of the app: when a user dismisses a
notification by swiping it away or clearing the whole notification
drawer. In this case, your app has no way of knowing that the
notification was canceled and that the button state must be changed.
Create another pending intent to let the app know that the user has
dismissed the notification, and toggle the button states accordingly.
Hint: Check out the NotificationCompat.Builder class for a method that
delivers an Intent if the user dismisses the notification.
package com.notifyme;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private NotificationManager mNotifyManager;
private static final int NOTIFICATION_ID = 0;
private static final String ACTION_UPDATE_NOTIFICATION =
"com.example.android.notifyme.ACTION_UPDATE_NOTIFICATION";
private static final String ACTION_CANCEL_NOTIFICATION =
"com.example.android.notifyme.ACTION_CANCEL_NOTIFICATION";
private NotificationReceiver mReceiver = new NotificationReceiver();
public class NotificationReceiver extends BroadcastReceiver {
public NotificationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_UPDATE_NOTIFICATION:
updateNotification();;
break;
case ACTION_CANCEL_NOTIFICATION:
cancelNotification();
break;
}
}
}
public void createNotificationChannel() {
mNotifyManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.O) {
// Create a NotificationChannel
NotificationChannel notificationChannel = new NotificationChannel(PRIMARY_CHANNEL_ID,
"Mascot Notification", NotificationManager
.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Notification from Mascot");
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
private Button button_notify;
private Button button_cancel;
private Button button_update;
public void sendNotification() {
Intent updateIntent = new Intent(ACTION_UPDATE_NOTIFICATION);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, updateIntent, PendingIntent.FLAG_ONE_SHOT);
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.addAction(R.drawable.ic_update, "Update Notification", updatePendingIntent);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, true, true);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_notify = findViewById(R.id.notify);
button_notify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendNotification();
}
});
createNotificationChannel();
button_update = findViewById(R.id.update);
button_update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Update the notification
updateNotification();
}
});
button_cancel = findViewById(R.id.cancel);
button_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Cancel the notification
cancelNotification();
}
});
registerReceiver(mReceiver,new IntentFilter(ACTION_UPDATE_NOTIFICATION));
setNotificationButtonState(true, false, false);
}
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}
public void cancelNotification() {
mNotifyManager.cancel(NOTIFICATION_ID);
setNotificationButtonState(true, false, false);
}
private NotificationCompat.Builder getNotificationBuilder(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this, PRIMARY_CHANNEL_ID)
.setContentTitle("You've been notified!")
.setContentText("This is your notification text.")
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(notificationPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
return notifyBuilder;
}
void setNotificationButtonState(Boolean isNotifyEnabled,
Boolean isUpdateEnabled,
Boolean isCancelEnabled) {
button_notify.setEnabled(isNotifyEnabled);
button_update.setEnabled(isUpdateEnabled);
button_cancel.setEnabled(isCancelEnabled);
}
}
Update: From CommonsWare's helpful answer below, I corrected the registration of the receiver to use multiple Actions for the same IntentFilter. However it still failed even though I tried all the different flags for the PendingIntent.
When you press the Update button in the notification and then swipe right, the buttons in the Activity do not reset their states because the PendingIntent is not firing.
Here is my updated code.
package com.onedropaflame.notifyme;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private NotificationManager mNotifyManager;
private static final int NOTIFICATION_ID = 0;
private static final String ACTION_UPDATE_NOTIFICATION =
"com.example.android.notifyme.ACTION_UPDATE_NOTIFICATION";
private static final String ACTION_CANCEL_NOTIFICATION =
"com.example.android.notifyme.ACTION_CANCEL_NOTIFICATION";
private NotificationReceiver mReceiver = new NotificationReceiver();
public class NotificationReceiver extends BroadcastReceiver {
public NotificationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_UPDATE_NOTIFICATION:
updateNotification();;
break;
case ACTION_CANCEL_NOTIFICATION:
cancelNotification();
break;
}
}
}
public void createNotificationChannel() {
mNotifyManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.O) {
// Create a NotificationChannel
NotificationChannel notificationChannel = new NotificationChannel(PRIMARY_CHANNEL_ID,
"Mascot Notification", NotificationManager
.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Notification from Mascot");
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
private Button button_notify;
private Button button_cancel;
private Button button_update;
public void sendNotification() {
Intent updateIntent = new Intent(ACTION_UPDATE_NOTIFICATION);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, updateIntent, PendingIntent.FLAG_ONE_SHOT);
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.addAction(R.drawable.ic_update, "Update Notification", updatePendingIntent);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, true, true);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_notify = findViewById(R.id.notify);
button_notify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendNotification();
}
});
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_CANCEL_NOTIFICATION);
intentFilter.addAction(ACTION_UPDATE_NOTIFICATION);
createNotificationChannel();
registerReceiver(mReceiver,intentFilter);
button_update = findViewById(R.id.update);
button_update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Update the notification
updateNotification();
}
});
button_cancel = findViewById(R.id.cancel);
button_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Cancel the notification
cancelNotification();
}
});
setNotificationButtonState(true, false, false);
}
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}
public void cancelNotification() {
mNotifyManager.cancel(NOTIFICATION_ID);
setNotificationButtonState(true, false, false);
}
private NotificationCompat.Builder getNotificationBuilder(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this, PRIMARY_CHANNEL_ID)
.setContentTitle("You've been notified!")
.setContentText("This is your notification text.")
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(notificationPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
return notifyBuilder;
}
void setNotificationButtonState(Boolean isNotifyEnabled,
Boolean isUpdateEnabled,
Boolean isCancelEnabled) {
button_notify.setEnabled(isNotifyEnabled);
button_update.setEnabled(isUpdateEnabled);
button_cancel.setEnabled(isCancelEnabled);
}
}
It appears as though you are not registering a receiver for ACTION_CANCEL_NOTIFICATION, just ACTION_UPDATE_NOTIFICATION.
Commonsware posted the correct answer about both actions needing to be registered.
However that was not sufficient. I corrected the registration of the receiver to use multiple Actions for the same IntentFilter. However it still failed even though I tried all the different flags for the PendingIntent. When you press the Update button in the notification and then swipe right, the buttons in the Activity do not reset their states because the PendingIntent is not firing.
Solution: I found that I had to set the cancelPendingIntent again during the updateNotification(). I do not know the reason why it is lost.
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
// >>>>> SET AGAIN! >>>>>>>>>
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
// >>>>>>>>>>>>>>
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}
I'm a beginner and I'm trying to show some status bar notification on the user.I found out that API23+ does not support the method setLatestInfo, so my compiler finds it as an error. What other method should I use instead of this to turn on notifications?
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import androidx.annotation.RequiresApi;
import static android.app.PendingIntent.getActivity;
import static android.content.Context.NOTIFICATION_SERVICE;
public class Settings extends AppCompatActivity {
Switch simpleswitch1;
Switch simpleswitch2;
private Notification notification;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
simpleswitch1 = (Switch) findViewById(R.id.simpleswitch1);
simpleswitch2 = (Switch) findViewById(R.id.simpleswitch2);
simpleswitch1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Notify("Title", "Message");
}
});
simpleswitch2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
notification.defaults |= Notification.DEFAULT_SOUND;
}});}
private void Notify(String notificationTitle, String notificationMessage) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.notification, "New message", System.currentTimeMillis());
Intent notificationIntent = new Intent(Settings.this, Settings.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(Settings.this, notificationTitle, notificationMessage, pendingIntent);
notificationManager.notify(9999, notification);
}
}
setLatestEventInfo is deprecated, was removed in api 23. So if your SDK version is set to api 23+ you'll have this issue and you should use NotificationCompat.Builder instead.
An example :
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
private void Notify(String notificationTitle, String notificationMessage) {
Intent notificationIntent = new Intent(Settings.this, Settings.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification)
.setContentTitle("New message")
.setContentText("My notification")
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.build();
Notification notification = builder.getNotification();
notificationManager.notify(11 /*An identifier for this notification unique within your application.*/, notification);
}
I suggest to read the official documentation about notification here.
I'm having an issue with trying to run an activity when a notification is clicked.
How and where create a Pending Intent, which must run my app after i click on notification..? I dont have problems with notification. But my notification after click doesnt work. Please help, thanks ..............................................................................................................................................................................................................................................
package pl.wat.pz.myapplication;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
private static final String GROUP_UPDATES="group_updates";
private static final String CHANNEL_CONTENT="channel_content";
private static final int NOTIF_ID_CONTENT=1337;
private NotificationManager mgr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mgr=getSystemService(NotificationManager.class);
if (mgr.getNotificationChannel(CHANNEL_CONTENT)==null) {
initContentChannel();
}
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.actions, menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.settings) {
Intent i=new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(i);
}
return super.onOptionsItemSelected(item);
}
public void raiseContent(View view) {
Notification n=new NotificationCompat.Builder(MainActivity.this, CHANNEL_CONTENT)
.setContentTitle(getString(R.string.notif_content_title))
.setContentText(getString(R.string.notify_content_text))
.setSmallIcon(android.R.drawable.stat_sys_warning)
.build();
mgr.notify(NOTIF_ID_CONTENT, n);
}
private void initContentChannel() {
NotificationChannel channel=
new NotificationChannel(CHANNEL_CONTENT,
getString(R.string.channel_name_content),
NotificationManager.IMPORTANCE_LOW);
channel.setGroup(GROUP_UPDATES);
mgr.createNotificationChannel(channel);
}
}
You use of intent to your class to extend of FirebaseMessagingService and your intent code is like to below :
Intent intent = new Intent(context, yourClass.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
requestCode,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
// then set to notification
NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
bigPictureStyle.setBigContentTitle(title);
bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
bigPictureStyle.bigPicture(bitmap);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(bigPictureStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);