I'm developing an android application where I want to add a Phone Button in Status Bar. Can I add a Phone button in Status Bar?
I want to add a button like showing in the above Image. I tried to do with the notification but the notification icon size is too small. How can I do it? Any Idea?
I think it goes against the design guidelines to put a button in the status bar since it's supposed to contain notification and system icons only. See https://material.io/design/platform-guidance/android-bars.html#status-bar.
Try a heads-up notification instead (https://developer.android.com/guide/topics/ui/notifiers/notifications.html).
You can put the button in the action area of the notification (https://material.io/design/platform-guidance/android-notifications.html#anatomy-of-a-notification).
Looks like you need foreground service with notification icon -
here
Sample code for foreground service -
public class ExampleService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Example Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
//do heavy work on a background thread
//stopSelf();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Related
I have created a foreground service using the following code which is in the override method OnStartCommand inside a service class called DemoIntentService.cs.
base.OnStartCommand(intent,flags,startId);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
Intent notificationIntent = new Intent(this, Java.Lang.Class.FromType(typeof(DemoIntentService)));
PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, 0);
Notification.Builder notificationBuilder = new Notification.Builder(this, "Example_Service_Channel")
.SetSmallIcon(Resource.Drawable.AlertLightFrame)
.SetContentTitle(Resources.GetString(Resource.String.DialogAlertTitle))
.SetContentText(Resources.GetString(Resource.String.SelectTextMode))
.SetContentIntent(pendingIntent);
Notification notificationAfterBuild = notificationBuilder.Build();
StartForeground(123, notificationAfterBuild);
InitializeAlarmManager();
setAlarm();
}
return StartCommandResult.RedeliverIntent;
Obviously, the code above is only for Android Oreo 8.0 and above, the service works fine and the notification will not be cleared even though I close the app manually. (That's good, that's what I want !). However, when I use the above code to test on Android Nougat 7.1.1, it would not work.
Firstly, I have researched online they said there is no need to create a notification channel for Android below 8.0, so I remove the "Example_Service_Channel" which is the channelID. The app was deployed successfully, but the notification gone when I kill the app. Second thing, when I removed the channelID, Xamarin throw me a warning said "Notification.Builder.Builder(Context) is obsolete : deprecated" and the line has turn yellow. I ignore the error and deploy the app. The service did run as it is visible in the running service inside the developer options. But when I killed the app, the service and notification gone together. Is there any other way to create a foreground notification service that will never end for Android below 8.0? Thanks for any comment and idea.
i write a simple sample,and it works on Android 7.1. i just delete the Notification Channel from Android 8.0
1.Create a Service MyService.cs :
[Service(Enabled = true)]
public class MyService : Service
{
private Handler handler;
private Action runnable;
private bool isStarted;
private int DELAY_BETWEEN_LOG_MESSAGES = 5000;
private int NOTIFICATION_SERVICE_ID = 1001;
private int NOTIFICATION_AlARM_ID = 1002;
public override void OnCreate()
{
base.OnCreate();
handler = new Handler();
//here is what you want to do always, i just want to push a notification every 5 seconds here
runnable = new Action(() =>
{
if (isStarted)
{
DispatchNotificationThatAlarmIsGenerated("I'm running");
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
}
});
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (isStarted)
{
// service is already started
}
else
{
DispatchNotificationThatServiceIsRunning();
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
isStarted = true;
}
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
//base.OnTaskRemoved(rootIntent);
}
public override IBinder OnBind(Intent intent)
{
// Return null because this is a pure started service. A hybrid service would return a binder that would
// allow access to the GetFormattedStamp() method.
return null;
}
public override void OnDestroy()
{
// Stop the handler.
handler.RemoveCallbacks(runnable);
// Remove the notification from the status bar.
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(NOTIFICATION_SERVICE_ID);
isStarted = false;
base.OnDestroy();
}
//start a foreground notification to keep alive
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.Icon)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
}
//every 5 seconds push a notificaition
private void DispatchNotificationThatAlarmIsGenerated(string message)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
Notification.Builder notificationBuilder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.Icon)
.SetContentTitle("Alarm")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build());
}
}
2.in your activity :
protected override void OnResume()
{
base.OnResume();
StartMyRequestService();
}
public void StartMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyService));
StartService(serviceToStart);
}
try to start the service with
ContextCompat.startForegroundService(context,intent)
build the notification then call
startForeground(1, notification)
in onCreate() or onStartCommand() whatever works for you but after the service started and running don't forget to ask for permission
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
I am new to android. I have already developed android application which starts service when application starts.
What I have :
Currently when application starts, it creates sticky notification in notification area as shown in screenshot.
Source code for service :
public class InfiniteService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Intent notificationIntent = new Intent();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText("Welcome To TestApp")
.setContentIntent(pendingIntent).build();
startForeground(1337, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Log.e("InfiniteService", "Service started");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
//Log.e("InfiniteService", "onDestroy");
sendBroadcast(new Intent("InfiniteService"));
}
What I want :
I want to get rid of this sticky notification in notification area. Instead I want service that runs in background continuously.
What I have tried :
I tried 'return START_NON_STICKY' in onStartCommand with initial impression that it will remove sticky notification but later learned from here that START_STICKY tells the OS to recreate the service after it has enough memory
I was suspecting PendingIntent is making this but again after reading explanation, come to know that it is not what I am looking for.
Then I searched how to create sticky notification in android hoping to get some clue. After reading this article, got to know flags makes it sticky. I searched "Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT" in my entire code but did not find anything.
What am I missing? Any pointers/help would be great. Thanks.
I did like to ask how I can go about the implementation of a customized notification even when the phone is locked.
e.g., i have this service that helps with push notification already.
public class NotifyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(), HomeMenuActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification mNotify = new Notification.Builder(this)
.setContentTitle("Checker")
.setContentText("Welcome here")
.setSmallIcon(R.drawable.app_icon)
.setContentIntent(pIntent)
.setSound(sound)
.addAction(0, "Loading...", pIntent)
.build();
mNM.notify(1, mNotify);
}
}
But, I did like to know how I can go about the implementation of something like the attached image below.
the appearing of notification on lock screen is started from lollipop version.So you need to set priority max or high of notification then it will be shown on lock screen when device is locked and also will be shown as heads up notification.
I am working on an app where I have a service that should always run in the background. This service is responsible for a Notification bar that should always be visible. The notification bar has 2 buttons, where the 1st one is for grabbing some data and storing it and the 2nd one should open an activity that will show all the data. I encountered a problem where when I close the application and then press the notification button that starts an activity after that activity starts, my notification buttons stop responding. Note that both buttons work fine before the point where the 2nd button click starts the activity.
Here is a template code for my notification service and for notification bar button handler
service that handles the Notification bar
public class NotificationBarService extends Service {
private int notificationID;
#Override
public IBinder onBind(Intent intent){
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
notificationID = new Random().nextInt();
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
contentView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
contentView.setTextViewText(R.id.title, "Custom notification");
contentView.setTextViewText(R.id.text, "This is a custom layout");
//Handle the button for showing bookmarks on custom notification
Intent buttonsIntent2 = new Intent(this, NotificationBarButtonActivityHandler.class);
buttonsIntent2.putExtra(PENDING_ACTION, SHOW_BOOKMARKS);
contentView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton, PendingIntent.getActivity(this, 0, buttonsIntent2, 0));
//Handle the button for adding bookmark on custom notification
Intent buttonsIntent = new Intent(this, NotificationBarButtonActivityHandler.class);
buttonsIntent.putExtra(PENDING_ACTION, REGISTER_BOOKMARK);
contentView.setOnClickPendingIntent(R.id.notificationBarAddBookmarkFromChromeButton, PendingIntent.getActivity(this, 1, buttonsIntent, 0));
RemoteViews notificationView = new RemoteViews(getPackageName(),
R.layout.custom_notification);
Intent switchIntent = new Intent(this, NotificationBarService.class);
PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 0,
switchIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton,
pendingSwitchIntent);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContent(contentView)
.setSmallIcon(R.drawable.notification_small_icon)
.setOngoing(true);
Notification notification = mBuilder.build();
startForeground(notificationID, notification);
return START_STICKY;
}
#Override
public void onDestroy(){
super.onDestroy();
stopForeground(true);
}
}
Class that handles the button press on Notification bar
public class NotificationBarButtonActivityHandler extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String action = (String) getIntent().getExtras().get(NotificationBarService.PENDING_ACTION);
if (action != null) {
if (action.equals(NotificationBarService.REGISTER_BOOKMARK)){
CustomLogger.log("---------------- BUTTON FOR COLLECT DATA WAS PRESSED!!!");
//Does something here
}
else if(action.equals(NotificationBarService.SHOW_BOOKMARKS)){
CustomLogger.log("---------------- BUTTON FOR SHOW DATA WAS PRESSSED!!!");
//Notification bar buttons start not responding right after
//this is executed. Note that this problem only occurs if I close the app
//and press the notification button to execute this code.
//Otherwise this works just fine.
Intent intent2;
intent2 = new Intent(this, BookmarkDisplayActivity.class);
startActivity(intent2);
}
}
finish();
}
}
So basically if I close the application and remove the code that starts the activity, both buttons work as expected but as soon as I start the activity, both buttons stop working.
Ok, I finally solved the issue that I was having with changing the way that I handle button presses. This is what I got now and it works as expected.
In NotificationBarService this is how I handle the listeners for the buttons
Intent addBookmarkIntent = new Intent(this, NotificationBarButtonListener.class);
addBookmarkIntent.setAction(ADD_BOOKMARK_ACTION);
PendingIntent pendingAddBookmarkIntent = PendingIntent.getBroadcast(this, 0, addBookmarkIntent, 0);
contentView.setOnClickPendingIntent(R.id.notificationBarAddBookmarkFromChromeButton, pendingAddBookmarkIntent);
Intent showBookmarkIntent = new Intent(this, NotificationBarButtonListener.class);
showBookmarkIntent.setAction(SHOW_BOOKMARK_ACTION);
PendingIntent pendingShowBookmarkIntent = PendingIntent.getBroadcast(this, 0, showBookmarkIntent, 0);
contentView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton, pendingShowBookmarkIntent);
and then I receive a broadcast even and handle it like this
public static class NotificationBarButtonListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(action.equals(ADD_BOOKMARK_ACTION)){
CustomLogger.log("---------------- BUTTON FOR REGISTER BOOKMARK WAS PRESSED!!! ");
}
else if(action.equals(SHOW_BOOKMARK_ACTION)){
CustomLogger.log("---------------- BUTTON FOR SHOW BOOKMARK WAS PRESSSED!!!");
}
}
}
Note that this required me to add the following line to my manifest
<receiver android:name=".NotificationBarService$NotificationBarButtonListener"/>
I'm trying to cancel an upload service from my progress notification using the 'cancel' button.
But I cannot get this working.
Notification is created
//Intent class changes from first activity then to service when it's uploading.
Intent cancel = new Intent(intentClass, BaseUploadService.class);
PendingIntent cancelUploadIntent = PendingIntent.getBroadcast(intentClass, 0, cancel, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder
.setSmallIcon(R.drawable.notificationicon)
.setContentTitle(title)
.setContentText(filename)
.setAutoCancel(totalAmount > uploadedAmount)
.setProgress((int) totalAmount, (int) uploadedAmount, false)
.addAction(R.string.assignment_icon_group, intentClass.getString(R.string.cancel), cancelUploadIntent)
;
return builder.build();
Listen for intent from notification button.
public class BaseUploadService extends IntentService {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.debug("onStartCommand - BaseUploadService");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
public BaseUploadService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
}
}
Nothing is ever received in the service.
+ there could be multiple services.
Change PendingIntent.getBroadcast() to PendingIntent.getService().
If after that change the service is still not started, try building the notification with setContentIntent instead of addAction.
Check your manifest to confirm that BaseUploadService is declared correctly.