How to post a notification with no icon but with led enabled? - android

Hi fellow Android coders !
I'm currently writing an application that uses the new Android 4.3 notification listener to change the notification led color when a notification is received, and am facing a problem, probably due to my lack of knowledge about how notifications work.
So far, it is working quite well. When the user switch off the screen, I create a notification, with a custom led color, and I remove it when the screen is switched ON. My problem is that when the user switch the screen back ON, he can see my notification icon on the status bar for half a second just before it is removed. Not that big of a deal, but as a nit-picker, I can't help but try a way to avoid this ugly behavior. I know that some apps succeed as doing this - LightFlow for example.
My first idea was to play with the priority of the notification and using Notification.PRIORITY_MIN nearly worked : the notification icon is not displayed on the status bar but appears when the bar is expanded.
I unfortunately discovered that notifications with minimum priority doesn't toggle the notification led when the screen is off !
I then tried to create a notification with no icon, but it is not supported by the framework - that's actually a good thing.
And now I'm out of idea.
Can someone help my find a way to create a notification that doesn't appear on the status bar but still toggles the LED on ?
Or maybe should I remove my notification before the screen is actually switched ON but I can't find a way to do this either...
If someone can help me on this one, it would make my day !
Here is the code source of my application :
Main activity :
package com.nightlycommit.coloration;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Service listener
package com.nightlycommit.coloration;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.service.notification.StatusBarNotification;
/**
* Created by Eric on 08/08/13.
*/
public class NotificationListenerService extends android.service.notification.NotificationListenerService {
private final String TAG = getClass().getSimpleName();
#Override
public void onCreate() {
super.onCreate();
// REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenStateReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String text = "Notification posted !";
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
String text = "Notification removed !";
}
}
Screen state receiver :
package com.nightlycommit.coloration;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
/**
* Created by Eric on 12/08/13.
*/
public class ScreenStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String action = intent.getAction();
if (action != null) {
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Notification.Builder builder = new Notification.Builder(context);
builder.setLights(Color.argb(255,255,0,0), 500, 500);
builder.setContentText("TEST");
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setOngoing(true);
// builder.setPriority(Notification.PRIORITY_MIN);
notificationManager.notify(777, builder.build());
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
notificationManager.cancel(777);
}
}
}
}
Thanks by advance,
Eric.

Related

Foreground service notification always shown for at least 5 seconds

I noticed some very strange behavior when testing foreground notifications on Android 9.
Situation: I have some foreground services where I don't know how long they'll need to run for, be it 1 second or a whole minute. Finally, when the service is done, it will call stopForeground(true). This used to work fine on all Android 8, 9 and 10 devices, where stopForeground(true), even if called immediately, always reliably removed the notification.
Problem: Testing on a Fairphone 3 (and I hope someone else encountered this on some other devices, because for me this is not happening on any emulator or other device), stopForeground is not working as expected. Instead of immediately removing the notification, the notification always shows for at least 5 seconds, even if I call stopForeground straight away. These 5 seconds happen to be the exact 5 second limit of the dreaded error Context.startForegroundService() did not then call Service.startForeground() - still a problem. Very peculiar! Reproducing this and checking whether your device is affected is very easy with the code below.
Inside AndroidManifest.xml:
<service
android:name="<your package name>.TestService"
android:exported="false" />
Class TestService.java:
package <your package name>;
import android.annotation.TargetApi;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
#TargetApi(Build.VERSION_CODES.O)
public class TestService extends Service {
#Override
public void onCreate() {
super.onCreate();
showNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
showNotification();
stopForeground(true);
return super.onStartCommand(intent, flags, startId);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void showNotification() {
String channelId = "TEST";
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager.getNotificationChannel(channelId) == null)
notificationManager.createNotificationChannel(new NotificationChannel(channelId, "TEST NOTIFICATIONS", NotificationManager.IMPORTANCE_DEFAULT));
startForeground(1, new NotificationCompat.Builder(this, channelId).setContentText("TEST NOTIFICATION").build());
}
}
Finally, simply start the service (for example on button click) via startForegroundService(new Intent(this, TestService.class));
Has anyone else experienced this issue or is able to reproduce it with the code above? How can I fix or even just debug it, considering I'm testing on Android 9 and the behaviour is different simply because of the OEM?
Latest security patch claims that it's normal behaviour:
https://issuetracker.google.com/issues/147792378
However I'm not sure why it's happening already on Android 9.

trouble implementing android notifications

I would greatly appreciate any help with troubleshooting my use of notifications within the Android emulator. I have tried several different versions without success and the code below seems to distill the needed elements down to the minimum. The problem is that the notification simply doesn't get sent. I hear the "click" noise when I tap the button in the emulator but nothing else.
I had read somewhere that having the wrong type of image may cause problems and I have tried several. The one I have included now is generated using Vector Asset within the res folder. It feels like there is something simple that I am missing but from what I can see from all the examples I have found online the basic elements are sound.
Any help or direction would be appreciated.
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class MainActivity extends AppCompatActivity {
NotificationCompat.Builder notification;
private static final int idNumber = 123;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
notification = new NotificationCompat.Builder(this);
notification.setAutoCancel(true);
}
public void sendNotification(View view){
notification.setSmallIcon(R.drawable.ic_android_black_24dp);
notification.setContentText("This is the notification message");
notification.setContentTitle("Notification");
notification.setTicker("There is a notification");
notification.setWhen(System.currentTimeMillis());
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
nm.notify(idNumber, notification.build());
}
}

changing UI elements if app is in the foreground from a broadcast receiver

I Have a BroadcastReceiver set up to turn Bluetooth on and off according to power state (when plugged in, bluetooth is on, unplugged, bluetooth is off). This is working just fine (yay!). however, my very simple app has a single button, which also turns Bluetooth on and off, and has the text "Bluetooth on" or "Bluetooth Off", as applicable. I would like to update this single button, BUT, I only have to update it if the app is in the foreground.
Inside onResume on m,y main activity, I'm calling my updateUI method, which checks the Bluetooth state, and updates the button accordingly. however, that only applies if the program was open and in the background, and is resumed, NOT if i'm in the program while plugging/unplugging the power.
I created a new activity (CheckIfAppIsRunningActivity.java) with this code which is supposed to check if my app is running in the foreground, and if so, take it to the activity (BluetoothOnActivity) which will update the button:
package vermel.BluetoothOn;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CheckIfAppIsRunningActivity extends Activity{
public void onCreate() {
checkStatus();
}
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it);
}
};
public void checkStatus() {
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager.getRunningAppProcesses();
for(int i = 0; i < runningProcInfo.size(); i++){
if(runningProcInfo.get(i).processName.equals("vermel.BluetoothOn")) {
if (runningProcInfo.get(i).lru == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
//start activity
/* Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it); */
}
}
}
}
}
and i'm pointing to it from my broadcast receiver:
package vermel.BluetoothOn;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Button;
import android.widget.Toast;
public class BTDetector extends BroadcastReceiver {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
public void onReceive(Context context , Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
//TODO if app is open, change text on button to on
//Toast.makeText(context, "turned on bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
} else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
if (mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
//TODO if app is open, change text on button to off
//Toast.makeText(context, "turned off bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
}
}
}
a few things: yes, I know i'm not supposed to use .enable() without user permission. in a weird way, plugging in the phone IS my user permission, since this is ALL that this app does, so, it's not sneaky, since you know what you're getting when you're installing the app.
The commented stuff is mostly things i've tried in vain..
I'm very open to the fact that i'm making this WAY harder than I need to...
so, as i said, it does turn Bluetooth on and off beautifully, but simply crashes after that. I can't debug it, since the emulator doesn't have Bluetooth , and i'm disconnecting the phone to get the crash result, so, it's not logging anything, since it's now connected...
I'm new in both Java and Android, and would appreciate a bit of patience. I try reading the official android documentation, but that's like chinese to me... so, an extended explanation would be great...
Thanks for reading!

Android Honeycomb notification popup too frequently

I am developing for Honeycomb and for days i am trying to solve this problem.
I have an notification service without intent (don`t need one), the problem is that after every call for displaymessage function the notification pup-up each time, so i get 100 notifications. I would like it to popup only once and after that only change the text of percent. Similar to downloading from market progress bar and percentage. I have isolated the function and created new testing code but with no success. If you look at this from other angle, i wish to change the text on existing notification without creating new notification.
Can you please help me?
Here is the whole code (after the isolation):
package com.disp;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
public class DispalyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i = 0; i < 100; i++) {
SystemClock.sleep(300);
displaymessage(""+i+"%");
}
}
public void displaymessage(String string) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
Notification notification = new Notification(R.drawable.ic_launcher, "Notification Service", System.currentTimeMillis());
Context context = getApplicationContext();
notification.setLatestEventInfo(context, "Downloading Content:", string, null);
final int HELLO_ID = 2;
mNotificationManager.notify(HELLO_ID, notification);
}
}
Because each notification is uniquely identified by the NotificationManager with an integer ID, you can revise the notification by calling setLatestEventInfo() with new values, change some field values of the notification, and then call notify() again.
You can revise each property with the object member fields (except for the Context and the notification title and text). You should always revise the text message when you update the notification by calling setLatestEventInfo() with new values for contentTitle and contentText. Then call notify() to update the notification. (Of course, if you've created a custom notification layout, then updating these title and text values has no effect.)
from
http://developer.android.com/guide/topics/ui/notifiers/notifications.html

launch activity from service when notification is clicked

I know, there are tons of these on here, but I've been trying solutions all day and haven't gotten anywhere.
Neither the example on google's docs, nor any of the 5 other ways I've found on here have worked for me at all.
As is the typical case, when I click the notification it closes the status bar and nothing new is shown onscreen.
I am creating the notification from a service and need the notification to trigger a new activity that has not yet been created.
I also will need a way to pass information to that activity via intent.
And yes... this is java for Android
What follows are the shattered remnants of my code.
package com.bobbb.hwk2;
import java.io.FileOutputStream;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.widget.Toast;
public class contactBackup extends Service
{
private NotificationManager nManager;
private static final int NOTIFY_ID = 1100;
#Override
public void onCreate()
{
super.onCreate();
String ns = Context.NOTIFICATION_SERVICE;
nManager = (NotificationManager)getSystemService(ns);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// inform user that service has started
Toast.makeText(getApplicationContext(), R.string.service_started,Toast.LENGTH_LONG).show();
String data = lookUpContacts();
if( saveToSDCard(getResources().getString(R.string.backup_file_name),data) )
{
Context context = getApplicationContext();
// create the statusbar notification
Intent nIntent = new Intent(this,contactViewer.class);//Intent nIntent = new Intent(Intent.ACTION_MAIN);
nIntent.setClass(context,contactViewer.class);
//nIntent.putExtra("data",data);
Notification msg = new Notification(R.drawable.icon,"All contacts records have been written to the file.",System.currentTimeMillis());
// start notification
//PendingIntent pIntent = PendingIntent.getService(getApplicationContext(),0,nIntent,PendingIntent.FLAG_UPDATE_CURRENT|Intent.FLAG_FROM_BACKGROUND);
PendingIntent pIntent = PendingIntent.getActivity(this,0,nIntent,0);
msg.flags = Notification.FLAG_AUTO_CANCEL;
msg.setLatestEventInfo(context,
"success",
"All contacts records have been written to the file.",
pIntent);
nManager.notify(NOTIFY_ID,msg);
}
}
#Override
public void onDestroy()
{
nManager.cancel(NOTIFY_ID);
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
// function returns string containing information
// from contacts
public String lookUpContacts()
{
...
}
public boolean saveToSDCard(String fileName, String data)
{
...
}
}
I can only hope that whatever is causing my problem is something fixable and not more of the crazy glitches I've been getting with eclipse (which no one else seems to have ever seen >:U )
If you can help me solve this problem, please share.
If you can't help with this specific problem but feel obligated to say unrelated things about posting, styles, topics, or good practice, then DON'T
Thank you :D
Edit:
You're going to have to add a flag for FLAG_ACTIVITY_NEW_TASK:
nIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This is because you're launching from outside your app (from the system notification bar).
This is what happens when people overwork themselves. XD
The only reason none of the tutorials I tired worked is because I misspelled my activity name in the manifest.
Thanks for stopping by
Just add following in contactBackup(service class),
Intent nIntent = new Intent(this,contactViewer.class);//Intent nIntent = new Intent(Intent.ACTION_MAIN);
nIntent.setClass(context,contactViewer.class);
nIntent.putExtra("data",data);
nIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Notification msg = new Notification(R.drawable.icon,"All contacts records have been written to the file.",System.currentTimeMillis());
// start notification
//PendingIntent pIntent = PendingIntent.getService(getApplicationContext(),0,nIntent,PendingIntent.FLAG_UPDATE_CURRENT|Intent.FLAG_FROM_BACKGROUND);
PendingIntent pIntent = PendingIntent.getActivity(this,0,nIntent,0);
msg.flags = Notification.FLAG_AUTO_CANCEL;
msg.setLatestEventInfo(context,
"success",
"All contacts records have been written to the file.",
pIntent);
nManager.notify(NOTIFY_ID,msg);
then get value in contactViewer class,
as,
String s=getIntent().getStringExtra("data");

Categories

Resources