my question is for I can't see the background in my Android Wear emulator, I declare .setBackgroung with a validated image but when I run the App and send me a notification the background does not show.
Any help?
public class NotificationService extends FirebaseMessagingService {
public static final String TAG = "FIREBASE";
public static final int NOTIFICATION_ID = 001;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//super.onMessageReceived(remoteMessage);
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
enviarNotificacion(remoteMessage);
}
public void enviarNotificacion(RemoteMessage remoteMessage){
Intent i = new Intent();
i.setAction("TOQUE_ANIMAL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Uri sonido = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.ic_full_poke,
getString(R.string.texto_accion_toque), pendingIntent)
.build();
NotificationCompat.WearableExtender wearableExtender =
new NotificationCompat.WearableExtender()
.setHintHideIcon(true)
.setBackground(BitmapFactory.decodeResource(getResources(),
R.drawable.bk_androidwear_notification))
.setGravity(Gravity.CENTER_VERTICAL);
NotificationCompat.Builder notificacion = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notificacion)
.setContentTitle("Notificacion")
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(sonido)
.setContentIntent(pendingIntent)
.extend(wearableExtender.addAction(action))
//.addAction(R.drawable.ic_full_poke, getString(R.string.texto_accion_toque), pendingIntent)
;
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
notificationManager.notify(NOTIFICATION_ID, notificacion.build());
}
}
You may refer with this SO post. Try to use setBackground(Bitmap) method from WearableExtender instead of setLargeIcon(Bitmap). You may also check this tutorial on how to create a watchface for Android Wear.
Additional reference to set background image for Android Wear notification: Background image for android wear notification
The resolution for square watch faces as of right now is 280x280, whereas the circular watch face has a resolution of 320x320 (although some of this will be cut off, obviously).
However, Android Wear implements a sort of parallax scrolling by default for larger images, so it can handle larger images with great ease, and it is even recommended that you do so (see this previous answer). So you really shouldn't worry about the size of the image, unless you were trying to create a static, full-screen image with specific areas of interaction as a substitute for custom UI elements (which you can do, I might add, although Google recommends you have only one area of interaction per screen on the watch to keep things simple).
If you want to see a good example of multiple images being used for backgrounds with parallax scrolling, I recommend you check out the GridViewPager sample project, which can be found in the SDK samples in the wearable subfolder for API level 20.
Hope this helps!
Related
I'm trying to implement a custom notification sound in my application.
I have written the following code, but the application plays only default sound and not the custom sound i've added in raw folder. Upon receiving the notification, the logs doesn't even throw any error or exception as to why it isn't playing the custom sound. I tried searching online and tried following different approaches but to no avail.
Please let me know where am i going wrong.
Edit: Can someone post the code for it, i cant seem to find anything that works
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.notify);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("MyCuS Notification", "My Notification", NotificationManager.IMPORTANCE_HIGH);
NotificationManager manager = getSystemService(NotificationManager.class);
AudioAttributes.Builder audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
channel.setSound(Uri.parse("android.resources://" + getPackageName() + "/" + R.raw.bg_reminder_alarm),audioAttributes.build());
manager.createNotificationChannel(channel);
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, "MyCuS Notification");
builder.setContentTitle("MyTitle");
builder.setContentText("TESTING");
builder.setSmallIcon(R.drawable.ic_launcher_background);
builder.setAutoCancel(true);
builder.setSound(Uri.parse("android.resources://" + getPackageName() + "/" + R.raw.bg_reminder_alarm));
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(MainActivity.this);
managerCompat.notify(1, builder.build());
}
});
}
Edit 2: I tried deleting existing channel and sending notification to create new channel, when newly created the description of the channel changes after sending second notification, it is as if the channel is overridden or deleted and new default channel is created.
Since Android Oreo / 8 the Notificationsound is coming from the Channel and can only be set the first time you add the channel via your channel.setSound().
If you want to change it later on you need to delete the channel and then re-add it to the system. The user will be warned about that behaviour though (App deleted channels X amount of times).
https://developer.android.com/guide/topics/ui/notifiers/notifications#ManageChannels
If you want to have a customsound each and every time, you need a ForegroundService without a channelsound for it's foreground notification (setSound(null)) and then use the MediaPlayer on the Notificationstream to play the custom sound.
I am using the notification payload below and use Postman to send a push notifications to Android devices:
{
"to" : "/topics/xxxx" ,
"data" : {
"url" : "https://res.cloudinary.com/demo/image/upload/w_200/lady.jpg",
"dl" : ""
},
"notification" : {
"title" : "This is a sample notification from general2",
"body" : "Rich notification testing (body)",
"image": "https://res.cloudinary.com/demo/image/upload/w_200/lady.jpg"
}
}
I have used the image key value pair to include an image in the push notification. My expected output is:
But this is what it is showing in the phone:
As you can see, the image is not appearing. What might be the problem?
I found out the problem is in aggressive battery savers. For example, Xiaomi and Samsung (Android 11 especially) phones will restrict FCM to do background networking (to fetch the image), thus, the image will be missing. This will only happen when phone is in deep sleep. If it's not (and your app is closed or in background), the image will be showing. If the app is in foreground, onMessageReceived() will be called and you need to fetch the image manually anyways and it will not be restricted by phone.
Sadly, I didn't find any workaround around this, except users manually disabling battery saving for your app :/
In-short
Uploading Image to a popular image hosting website and putting that link for notification image url worked for me. Also check image size i used (1000 × 500 px)
Expaned
I was also facing the same problem but creating MyFirebaseMessagingService did not help.
I was trying to load image from own hosting like (https://www.example.com/image/img.png).
Although it was https and firebase console was showing the image but on actual device it was not displayed.
For me uploading image to imggur.com or putting it in firbase storage and using that link for notification worked without any extra messaging service code.
This code might help
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMessagingServ";
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
sendNotification(bitmap);
}
#Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if(remoteMessage.getData()!=null)
getImage(remoteMessage);
}
private void sendNotification(Bitmap bitmap){
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.bigPicture(bitmap);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,0);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
String NOTIFICATION_CHANNEL_ID = "101";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
#SuppressLint("WrongConstant") NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Notification", NotificationManager.IMPORTANCE_MAX);
//Configure Notification Channel
notificationChannel.setDescription("Game Notifications");
notificationChannel.enableLights(true);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(Config.title)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentText(Config.content)
.setContentIntent(pendingIntent)
.setStyle(style)
.setLargeIcon(bitmap)
.setWhen(System.currentTimeMillis())
.setPriority(Notification.PRIORITY_MAX);
notificationManager.notify(1, notificationBuilder.build());
}
private void getImage(final RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
Config.title = data.get("title");
Config.content = data.get("content");
Config.imageUrl = data.get("imageUrl");
Config.gameUrl = data.get("gameUrl");
//Create thread to fetch image from notification
if(remoteMessage.getData()!=null){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable() {
#Override
public void run() {
// Get image from data Notification
Picasso.get()
.load(Config.imageUrl)
.into(target);
}
}) ;
}
}
}
you have to handle the reception of the image on your own,like said in the last line here of the official documentation:
With notification set as shown, this send request enables the receiving client to handle the image delivered in the payload.
Firesebase official documentation
2021 Working Solution:
override fun onMessageReceived(remoteMessage: RemoteMessage)
remoteMessage.notification?.let {
sendNotification(it.title!!, it.body!!, it.imageUrl) //image url in uri type
}
}
private fun sendNotification(title: String, message: String, imageUri: Uri?) {
...
val imageBitmap = imageUri?.let {
Glide.with(requireContext()).asBitmap().load(it).submit().get()
//you pick one, Glide or Picasso
Picasso.get().load(it).get()
}
...
}
Check your image size, mostly if you prefer to use an image less than or equal to 1 mb, mostly your issue will get resolved, I tried it and works in Xiaomi device.
I am working on a requirement to provide turn by turn navigation in one of our application. I am able to to build the app and works well. I have added custom notification feature to custom navigation activity, the notification works well but my device battery consumption is very high and some times I am getting warning this application is consuming more battery message.
Can any one help me on this point. I need to save the battery utilisation as well.
Here is my code snippet.
public class CustomNavigationNotification implements NavigationNotification {
private static final int CUSTOM_NOTIFICATION_ID = 91234821;
private Notification customNotification;
private NotificationCompat.Builder customNotificationBuilder;
private NotificationManager notificationManager;
private int numberOfUpdates;
public CustomNavigationNotification(Context context) {
// Get the notification manager to update your notification
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Store the builder to update later
customNotificationBuilder = new NotificationCompat.Builder(context, NAVIGATION_NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.caramaps_g)
.setContentTitle("App name")
.setContentText("Happy journey");
// Build the notification
customNotification = customNotificationBuilder.build();
}
#Override
public Notification getNotification() {
return customNotification;
}
#Override
public int getNotificationId() {
return CUSTOM_NOTIFICATION_ID;
}
#Override
public void updateNotification(RouteProgress routeProgress) {
// Update the builder with a new number of updates
customNotificationBuilder.setContentText("Diatance you traveled : " + routeProgress.distanceTraveled());
// Notify the notification manager
notificationManager.notify(CUSTOM_NOTIFICATION_ID, customNotificationBuilder.build());
}
}
Here I am passing custom notification to my navigation options builder.
MapboxNavigationOptions options1 = MapboxNavigationOptions.builder() .navigationNotification(mCustomNavigationNotification)
.maneuverZoneRadius(70)
.build();
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(currentRoute)
.directionsLanguage(Locale.getDefault())
.navigationOptions(options1)
.awsPoolId(null).shouldSimulateRoute(simulateRoute).build();
please suggest me if I am going wrong path....
Thanks in advance....
Ever since adding support for Android O, Android devices running O receive an alert (tone or vibration) whenever my app's media controls notification gets updated (metadata or playback state changes). I'm looking for a way to disable this alert since it's not applicable to media style notifications.
Here is the code I use to create a media controls notification:
MediaDescriptionCompat description = metadata.getDescription();
String artistName = metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
String albumName = metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM);
Bitmap largeIcon = BitmapFactory.decodeResource(playbackService.getResources(),
R.drawable.vector_global_defaultsong);
NotificationCompat.Builder notificationBuilder = new NotificationCompat
.Builder(playbackService, NotificationHelper.CHANNEL_MEDIA_CONTROLS)
.setColor(ContextCompat.getColor(playbackService, R.color.colorAccent))
.setSmallIcon(R.drawable.logo_light_filled)
.setContentTitle(description.getTitle())
.setContentText(playbackService.getString(R.string.song_list_subtitle_format,
artistName, albumName))
.setContentIntent(createContentIntent())
.setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(playbackService,
PlaybackStateCompat.ACTION_STOP))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOngoing(playbackState.getState() == PlaybackStateCompat.STATE_PLAYING)
.setLargeIcon(largeIcon);
notificationBuilder.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
// show previous, play/pause, and next in compact view
.setShowActionsInCompactView(addActions(notificationBuilder))
.setMediaSession(sessionToken));
showNotification(notificationBuilder.build());
. . .
private void showNotification(final Notification notification) {
if (!started) {
mediaController.registerCallback(mediaControllerCallback);
playbackService.startForeground(NOTIFICATION_ID, notification);
started = true;
} else {
notificationManager.notify(NOTIFICATION_ID, notification);
}
if (playbackState.getState() == PlaybackStateCompat.STATE_PAUSED) {
playbackService.stopForeground(false);
}
}
Here is the code I use to create the notification channel:
public static final String CHANNEL_MEDIA_CONTROLS = "media_controls";
public static void createNotificationChannels(Context context) {
if (android.os.Build.VERSION.SDK_INT >= 26) {
NotificationChannel mediaControlsChannel = new NotificationChannel(CHANNEL_MEDIA_CONTROLS,
context.getString(R.string.notification_channel_media_controls),
NotificationManager.IMPORTANCE_HIGH);
mediaControlsChannel.setShowBadge(false);
getNotificationManager(context).createNotificationChannel(mediaControlsChannel);
}
}
Update: Setting the showBadge to false on the notification channel doesn't appear to do anything. I still receive a badge on the app icon when the media controls notification is shown. So it looks like the notification channel attributes that I set are not being applied.
Per the Migrating MediaStyle notifications to Android O, you should be using IMPORTANCE_LOW, which does not contain any sound - IMPORTANCE_HIGH channels have sound associated with them.
Android already reorders MediaStyle notifications higher in the tray, so using a higher importance is not necessary as it was on previous versions of Android.
NOTE: After changing the importance, you need to clear app data or reinstall the app in order to have this change take effect in notification channel.
I wrote an IntentService for GCM Push Notifications.
I receive the Messages but something's wrong with displaying my Notification to the user.
Here's my Code:
import com.google.android.gms.gcm.GoogleCloudMessaging;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
public GcmIntentService() {
super("GcmIntentService");
}
public static final String TAG = "GCM test";
#Override
protected void onHandleIntent(Intent intent) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!intent.getExtras().isEmpty()) { // has effect of unparcelling Bundle
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server: " + intent.getExtras().toString());
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Post notification of received message.
sendNotification("message:\n" + intent.getStringExtra("message"));
Log.i(TAG, "Received: " + intent.getExtras().toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif)
.setContentTitle("My notification")
.setContentText(msg);
Intent resultIntent = new Intent(this, PopupMessageActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(PopupMessageActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
I don't see the mistake. I mean, I copied the code from the Androids developer guide.
The only thing that this code does, is that the small icon (in this case "ic_notif") is showing in the notification-bar of the phone.
But there's no Text or Notification that pops up to the user.
I use android-studio.
My debug device is an huawai u8666e with android 4.0.3 (API 15).
At least i want this API level to be my minimum requirement for this app.
What you are seeing is normal designed Android behaviour for versions before Lollipop.
The design logic is that this method creates a cleaner interface and will not interrupt the user's current actions by placing a popup in front of their face. (there is a lot of debate over which method is better - iOS popups vs Android notifications).
Lollipop changes this slightly by creating a small popup at the top of the device window when a Notification is created.
If you really want to force a popup dialog to be shown, you should be looking at designing a "full screen" Notification.
See the Android Developer docs:
Notication.Builder.setFullScreenIntent(Intent)
Using this method, you can create a new Activity with any custom layout you want, and launch that instead of placing the Notification in the status bar.
(full implementation of a full screen notification would be beyond the scope of this post)
I would recommend against forcing full screen notifications except in rare cases, such as an Alarm Clock, or Phone Call app. I would, instead, recommend that you stick to the way Android was designed and work with the OS.