I have a service which runs in foreground with, among other things, a stopwatch. When the service starts the notification appears, and when it ends I update it with sound and some text that indicates that it's finished. The problem is that this works well until api 25, but for 26 and 27 it updates the notification alright, but makes no sound. Here's the relevant code:
The creation of the notification inside the service:
mBuilder = new NotificationCompat.Builder(context, "Main")
.setSmallIcon(R.drawable.ic_notification_temp)
.setContentTitle(step.getDescription())
.setContentText(getString(R.string.notification_text))
.setVisibility(VISIBILITY_PUBLIC)
.setOngoing(true);
.setDeleteIntent(deletePendingIntent);
.setContentIntent(contentPendingIntent);
.addAction(R.drawable.ic_stop_red_24dp, getString(R.string.cancel),finnishPendingIntent);
mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, mBuilder.build());
The update to the notification builder when the "work" is finished:
mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
mBuilder.setVibrate(new long[]{0, 300, 0, 400, 0, 500});
mBuilder.setOngoing(false);
mBuilder.setAutoCancel(true);
mBuilder.setContentText(getString(R.string.notification_finished_text));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mBuilder.setChannelId("Sound");
mBuilder.setCategory(NotificationCompat.CATEGORY_ALARM);
}
mNotificationManager.notify(mId, mBuilder.build());
The 2 channels created just for api 26 or up on app start:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the normal NotificationChannel
CharSequence name = getString(R.string.app_name);
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel("Main", name, importance);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
// Create theNotificationChannel with sound
importance = NotificationManager.IMPORTANCE_HIGH;
name = getString(R.string.notification_channel_sound);
NotificationChannel sound = new NotificationChannel("Sound", name, importance);
sound.enableVibration(true);
sound.setVibrationPattern(new long[]{0, 300, 0, 400, 0, 500});
AudioAttributes aa = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
.build();
sound.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), aa);
notificationManager.createNotificationChannel(sound);
}
And that's where I'm at now. I've tried to not use setsound() as I've read that the notification should just play the default sound with the appropriate importance (and of course I've even uninstalled the app between tries to correctly update the channel settings) but nothing seems to work for api 26 and I just don't know what I'm doing wrong.
I had the exact same problems with most of my emulator AVDs. The following fixed it for me:
start the affected AVD
long press the AVD's power button
restart the AVD
Afterwards it should work again.
Tried to reproduce your issue and finished with created MVP, maybe this will help you to find the problem:
Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View btn = findViewById(R.id.clickMe);
btn.setTag(NotifService.CHANNEL_ID_MAIN);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String channelId = (String) v.getTag();
Intent intent = new Intent(v.getContext(), NotifService.class);
intent.putExtra(NotifService.TAG, channelId);
if (channelId.equals(NotifService.CHANNEL_ID_MAIN)) {
v.setTag(NotifService.CHANNEL_ID_SOUND);
} else {
v.setTag(NotifService.CHANNEL_ID_MAIN);
}
v.getContext().startService(intent);
}
});
}
}
Service:
public class NotifService extends IntentService {
public static final String TAG = "NotificationService";
public static final String CHANNEL_ID_MAIN = "Main";
public static final String CHANNEL_ID_SOUND = "Sound";
public static final int NOTIFICATION_ID = 123;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public NotifService() {
super(TAG);//Used to name the worker thread, important only for debugging.
}
#Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID_MAIN, "Channel Main", NotificationManager.IMPORTANCE_LOW);
NotificationChannel sound = new NotificationChannel(CHANNEL_ID_SOUND, "Channel Sound", NotificationManager.IMPORTANCE_HIGH);
sound.enableVibration(true);
sound.setVibrationPattern(new long[]{0, 300, 0, 400, 0, 500});
AudioAttributes aa = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
.build();
sound.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), aa);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
notificationManager.createNotificationChannel(sound);
}
}
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
String channelId = intent.getStringExtra(TAG);
showNotification(channelId);
}
private void showNotification(String channelId) {
boolean inProgress = channelId.equals(CHANNEL_ID_MAIN);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Work")
.setContentText(inProgress ? "InProgress" : "Finished")
.setOngoing(inProgress)
.setVisibility(VISIBILITY_PUBLIC)
.setAutoCancel(!inProgress);
if (!inProgress) {
builder.setCategory(NotificationCompat.CATEGORY_ALARM);
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
}
}
This works good on my device 8.1 and Emulator 8.1 (without sound on first click for first notification and with vibration + sound on second click for work complete notification).
Related
I have done notification on Android before and I haven't any problems with it. But, when I have tried to make notification by example for Wear OS I have an error. It says that: "Field to post a notification on channel: "my_channel_01""
public class MainActivity extends WearableActivity {
private TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text);
int notificationId = 001;
// The channel ID of the notification.
String id = "my_channel_01";
// Build intent for notification content
Intent viewIntent = new Intent(this, MainActivity.class);
viewIntent.putExtra("EXTRA_EVENT_ID", 1);
PendingIntent viewPendingIntent =
PendingIntent.getActivity(this, 0, viewIntent, 0);
createNotificationChannel();
// Notification channel ID is ignored for Android 7.1.1
// (API level 25) and lower.
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, id)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentTitle("Hello World")
.setContentText("eventLocation")
.setContentIntent(viewPendingIntent);
// Get an instance of the NotificationManager service
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
// Issue the notification with notification manager.
notificationManager.notify(notificationId, notificationBuilder.build());
// Enables Always-on
setAmbientEnabled();
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Test";
String description = "Notification for Wear OS";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("1", name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
} }
I have used SDK 28
In createNotificationChannel method, you need to set up id as id onCreate method like this:
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = "my_channel_01";
CharSequence name = "Test";
String description = "Notification for Wear OS";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(id, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
I've added a FirebaseMessagingService class to receive foreground notifications.
I don't receive foreground notifications.
In background when app minimized it works fine.
I've set the background notification with firebase functions and it works fine, now im trying to get this notification in foreground but the notifications doesn't appear.
my FirebaseMessagingService class:
public class FirebaseMessaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (remoteMessage.getNotification() != null) {
String notification_title = remoteMessage.getNotification().getTitle();
String notification_message = remoteMessage.getNotification().getBody();
Notification.Builder mBuilder = new Notification.Builder(this)
.setContentTitle(notification_title)
.setContentText(notification_message)
.setSmallIcon(R.drawable.default_avatar);
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
}
}
No error messages:
Actual results: notification never arrives in foreground.
Expected results: i want to receive the notification while im in the app not only when minimized.
i changed my FirebaseMEssagingService class to this it worked:
public class FirebaseMessaging extends FirebaseMessagingService {
private final String CHANNEL_ID = "personal_notifications";
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String notification_title = remoteMessage.getNotification().getTitle();
String notification_message = remoteMessage.getNotification().getBody();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.default_avatar)
.setContentTitle(notification_title)
.setContentText(notification_message);
notificationManager.createNotificationChannel(notificationChannel);
int mNotificationId = (int) System.currentTimeMillis();
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
}
}
I want to run a background function which listens to the clipboard and when a string greater than 200 characters is copied then it will execute the function to show notification and then the proper Activity.class.
I am unable to create a service which runs in the background all the time even when the app is closed and the phone is restarted. Current I am starting that function in MyApp class which extends Application as I am unable to understand any tutorial based on services which can give me what I want.
Below is my code for MyApp
MyApp.class
public class MyApp extends Application {
private PrefManager prefManager;
#Override
public void onCreate() {
super.onCreate();
prefManager = new PrefManager(this);
if (prefManager.isNotifOns()) {
getClipTexts();
}
}
//Listener to listen change in clipboard
private void getClipTexts() {
final ClipboardManager clipboardManager = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
clipboardManager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
try {
String textToPaste = clipboardManager.getPrimaryClip().getItemAt(0).getText().toString();
if (textToPaste.length() > 200) {
makeNotification(textToPaste);
}
} catch (Exception ignored) {
}
}
});
}
//Creating notifications after copying the clipboard text
public void makeNotification(String input) {
Intent notifIntent = new Intent(getApplicationContext(), PostActivity.class);
notifIntent.putExtra("post", input);
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 1;
String channelId = "channel-01";
String channelName = "Copy to Post";
int importance = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
importance = NotificationManager.IMPORTANCE_DEFAULT;
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Post copied content")
.setContentText(input)
.setAutoCancel(true);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addNextIntent(notifIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
}
Can anyone please write this function in a service which runs in background and supports in all Android Versions.
The above code does what I want as long as the app is running on foreground but I want to run the function even when App is closed or phone is restarted even in android versions above Android N. Please give me a proper answer I will be thankful for that.
I am stuck with my app which needs to repeat one notification after one hour (Medical purpose). As my field is totally opposite and I am noob in coding any help will be appreciated. I know I have to add something in notification receiver to repeat notifications. But every time I try to repeat the app crashes.
(This is a little but unique idea to solve a real world problem I will credit everyone from whom I've received even a little help )
Here is my MainActivity
private NotificationManagerCompat manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = NotificationManagerCompat.from(this);
}
public void Shownotification(View v) {
String title = "You Did it!";
String message = "Some Text";
Notification notification = new NotificationCompat.Builder(this, CHANNEL_1_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.build();
manager.notify(0,notification);
}
Notification Channel
public class App extends Application {
public static final String CHANNEL_1_ID = "channel1";
public static final String CHANNEL_2_ID = "channel2";
#Override
public void onCreate() {
super.onCreate();
createNotificationChannels();
}
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel1 = new NotificationChannel(
CHANNEL_1_ID,
"Channel 1",
NotificationManager.IMPORTANCE_HIGH
);
channel1.setDescription("This is Channel 1");
NotificationChannel channel2 = new NotificationChannel(
CHANNEL_2_ID,
"Channel 2",
NotificationManager.IMPORTANCE_LOW
);
channel2.setDescription("This is Channel 2");
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel1);
manager.createNotificationChannel(channel2);
}
}
Notification Reciever
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String title = "You Did it!";
String message = "Some Text";
Notification notification = new NotificationCompat.Builder(context, CHANNEL_1_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
Intent i = new Intent("android.action.DISPLAY_NOTIFICATION");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent broadcast = PendingIntent.getBroadcast(context, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), broadcast);
}
you can set new notification when previous one triggers.in onReceive Method of BroadcastReceiver.
I'm new to Android programming and I'm trying to build my first app. Right now I want to send local notifications. Unfortunately I cannot receive notifications on devices running API 28 and above. I know there is a change in the way notifications are sent since Oreo and I have included code that creates the channel. It seems like if I run the app on a simulator with a lower API (e.g. 19) the notification is received. Also if I copy my code into a new project I receive the notifications, even on a simulator running Android Oreo. What settings in the project could cause notifications not to be received on Android Oreo? (There are no errors in Logcat)
My code for sending the notifications:
public static final String CHANNEL_1_ID = "channel1";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createNotificationChannels();
}
public void setNotif(View view) {
Notification notification = new NotificationCompat.Builder(this, CHANNEL_1_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("hey")
.setContentText("world")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(1, notification);
}
private void createNotificationChannels() {
// if higher than android oreo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel1 = new NotificationChannel(CHANNEL_1_ID, "Channel 1", NotificationManager.IMPORTANCE_HIGH);
channel1.setDescription("This is channel 1");
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel1);
}
}
The setNotif method is called by a tap of a button. Again, I'm new to Android programming so any advice would be helpful. Maybe even a different way in which I could diagnose the issue. Thank you!
Add this check in your setNotif() method:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
notificationManager.createNotificationChannel(getNotificationChannel(context));
setNotif() method will be changed like this :
public void setNotif(View view) {
Notification notification = new NotificationCompat.Builder(this, CHANNEL_1_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("hey")
.setContentText("world")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) notificationManager.createNotificationChannel(getNotificationChannel(context));
notificationManager.notify(1, notification);
}
And getNotificationChannel() method will look like this:
private static NotificationChannel getNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return null;
CharSequence name = context.getString(R.string.app_name);// The user-visible name of the channel.
int importance = android.app.NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(BuildConfig.APPLICATION_ID, name, importance);
notificationChannel.setShowBadge(true);
return notificationChannel;
}