Is there a way to listen if a notification is updated. For example if I receive a message in Messenger my notification listener will notice that, but once I receive a second message - the notification listener ignores that.
I have tried with cancelling notifications, but that did not work
My notification listener:
public class Reader extends NotificationListenerService{
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
int id = sbn.getId();
String ticker = sbn.getNotification().tickerText.toString();
Bundle extras = sbn.getNotification().extras;
final String title = extras.getString("android.title");
String tag = sbn.getTag();
int ides = extras.getInt("android.id");
final String ss = extras.getString("android.text").toString();
final String text = ss.toLowerCase();
if (pack.equals("com.facebook.orca")) {
String e = "Tah";
Log.e(e, pack);
Log.e(e, ticker);
Log.e(e, title);
Log.e(e, ss);
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", ">" + text + "");
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
}
Related
I'm working on an android application that listens for notifications. Is there any way to get the name of the app which created the notification.
You need to get the package name first on receiving the new notification from the notification service::
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker = new String();
if(sbn.getNotification().tickerText != null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Bitmap id = sbn.getNotification().largeIcon;
}
And then use the "pack" value to get the app name:
final PackageManager pm = getApplicationContext().getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo( pack, 0);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ?
pm.getApplicationLabel(ai) : "(unknown)");
Through my android app I want to clear/remove message notification (that is generated by default in android device) of an incoming message if it contains keyword. Can anyone please help how can I do that?
use NotificationListenerService api and get notification id and text then clear notification by notification id.
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = "";
String ticker = "";
String title = "";
String text = "";
String postTime = "";
if (sbn.getPackageName() != null)
pack = sbn.getPackageName();
postTime = sbn.getPostTime() + "";
Bundle extras = sbn.getNotification().extras;
CharSequence data = extras.getCharSequence(Notification.EXTRA_TITLE);
extras.getCharSequence(Notification.EXTRA_TITLE);
if (data != null) {// notification title
title = data.toString();
}
data = extras.getCharSequence(Notification.EXTRA_TEXT);
if (data != null) {// notification text
text = data.toString();
}
String id= sbn.getKey() ;// notification id
}
I have an application that runs a service listens to notifications but it is showing all notification, I want to show only whatsapp notifications so I check if my package equals to com.whatsapp but then it's not showing nothing, code:
private BroadcastReceiver onNotice= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String pack = intent.getStringExtra("package");
String title = intent.getStringExtra("title");
String text = intent.getStringExtra("text");
if (pack == "com.whatsapp") {
TableRow tr = new TableRow(getApplicationContext());
tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
TextView textview = new TextView(getApplicationContext());
textview.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1.0f));
textview.setTextSize(20);
textview.setTextColor(Color.parseColor("#0B0719"));
textview.setText(Html.fromHtml(pack + "<br><b>" + title + " : </b>" + text));
tr.addView(textview);
tab.addView(tr);
}
}
};
}
am I checking if it equals wrong?
If needed, service code:
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker = sbn.getNotification().tickerText.toString();
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", text);
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
NOTE : when I remove the if statement,everything is working fine and it shows com.whatsapp as the package. thank you guys
You have to use the equals() method to compare Strings. == only compares their references, not their values.
if ("com.whatsapp".equals(pack)) {
// ...
}
check for package name before sending your broadcast.
if ("com.whatsapp".equals(pack)) {
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
I have an app that creates multiple alarms. Everything works fine, however, for some other functions (like updating a log) I need to retrieve the alarmID when the alarm is fired.
Here is the code the alarms are set with:
public void setAlarm(){
Intent intentAlarm = new Intent(c,AlarmReceiver.class);
intentAlarm.putExtra("userid", userid);
// create the object
AlarmManager alarmManager = (AlarmManager)
c.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getActivity(c, alarmID, intentAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,timeToMiliseconds(hour,minute),
AlarmManager.INTERVAL_DAY,alarmIntent);
Toast.makeText(c,"Alarm set for " + toTime(hour,minute),Toast.LENGTH_SHORT).show();
Log.d("setAlarm()",alarm.toString());
}
The alarm receiver is an activity (which works fine). I just need to retrieve the alarms ID that's currently being fired.
public class AlarmReceiver extends Activity {
private MediaPlayer mMediaPlayer;
private String scanContent;
private static final int ZBAR_SCANNER_REQUEST = 0;
String userid;
Button backBtn;
private PowerManager.WakeLock wakelock;
private ListView medBoxList;
ArrayList<HashMap<String, String>> medList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
ActionBar actionBar = getActionBar();
actionBar.hide();
/**
* Wakeup device if it's sleeping
*/
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
wakelock.acquire();
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
Intent alarmActivityIntent = getIntent();
userid = alarmActivityIntent.getStringExtra("userid");
playSound(this, getAlarmUri());
Toast.makeText(this, "Take Medication", Toast.LENGTH_LONG).show();
Button stopAlarm = (Button) findViewById(R.id.scanQR);
Button skipBtn = (Button) findViewById(R.id.skipBtn);
backBtn = (Button)findViewById(R.id.backBtn);
//Click button to scan and update userlog
//Click button to scan and update userlog
stopAlarm.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
mMediaPlayer.stop();
launchQRScanner();
}
});
//Click button to skip
skipBtn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
mMediaPlayer.stop();
}
});
}
private void playSound(Context context, Uri alert) {
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(context, alert);
final AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch (IOException e) {
System.out.println("OOPS");
}
}
//Get an alarm sound. Try for an alarm. If none set, try notification,
//Otherwise, ringtone.
private Uri getAlarmUri() {
Uri alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alert == null) {
alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if (alert == null) {
alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
}
}
return alert;
}
public void launchQRScanner() {
mMediaPlayer.stop();
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mMediaPlayer.stop();
scanContent = data.getStringExtra(ZBarConstants.SCAN_RESULT);
finish();
if(scanContent != null){
updateUserLog(scanContent);
Intent nextScreen = new Intent(getApplicationContext(),UserlogListActivity.class);
startActivity(nextScreen);
}
}
//Disable alarm with button instead of scan
public void alarmStopper(View v){
mMediaPlayer.stop();
Intent nextScreen = new Intent(getApplicationContext(),UserlogListActivity.class);
startActivity(nextScreen);
}
//TAKE MED ACTIVITY (MOVE TO )
public void updateUserLog(String scanContent){
//Toast.makeText(this, "Adding Userlog = " + scanContent, Toast.LENGTH_SHORT).show();
if(scanContent != null){
String userid,medname,tabstaken,dob;
//Break the scan content into strings for each variable
StringTokenizer st = new StringTokenizer(scanContent, ",");
dob = st.nextToken();
medname = st.nextToken();
tabstaken = st.nextToken();
if(dob != "" && medname != "" && tabstaken != ""){
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
HashMap<String,String> userLog = new HashMap<String, String>();
HashMap<String,String> user = new HashMap<String, String>();
user = db.getUserDetails();
//Store the userlog by passing to UserLogEntry
userid = user.get("uid");
if(userid != ""){
userLog = db.getNewestUserLogEntryForMed(medname);
String tabstr = userLog.get("tabsleft");
Log.d ("getNewestUserLogEntryForMed()", "medname " + userLog.get("medname") + " timetaken "
+ userLog.get("medtaken") + " Tabs - " + tabstr);
int tabs = Integer.parseInt(tabstr);
tabs = tabs - 1;
String tabsupdated = Integer.toString(tabs);
Log.d ("Tabs Updated - ", "medname " + userLog.get("medname") + " timetaken "
+ userLog.get("medtaken") + " Tabs - " + tabsupdated);
UserLogEntry userlog = new UserLogEntry(getApplicationContext(),userid,medname,tabsupdated);
userlog.addUserLog();
finish();
}
}
}
}
Any tips?
Much appreciated
So the answer was staring me in the face. I can use bundle to pass whatever I need into the alarm intent. I already was passing the userid (incorrectly). I just have to remember whenever there is an intent, that I can use bundle to pass simple variables along with it.
Intent intentAlarm = new Intent(c,AlarmReceiver.class);
Bundle extras = new Bundle();
extras.putString("userid", userid);
extras.putInt("alarmID", alarmID);
extras.putString("userlogID", userlogID);
extras.putString("medname", medname);
intentAlarm.putExtras(extras);
I figured I'd answer my own question in case someone else needs to do something similar, but if this is not helpful a moderator can delete it.
I've create a broadcast receiver that listen to the android.provider.Telephony.SMS_RECEIVED event and creates its own notification.
I also use the same receiver in the app to update the activities when an sms is received using a callback.
The problem is that the sms app notification event is dispatched after my notification, so when I update the sms is not preset in content://sms
I would like to delay my notification if it's possible, can't find how to do it.
here's the code:
public class SmsReceiver extends BroadcastReceiver {
Context context;
int nmessages = 0;
#Override
public void onReceive(Context context, Intent intent) {
//—get the SMS message passed in—
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String messages = "";
this.context = context;
if (bundle != null)
{
//—retrieve the SMS message received—
Object[] smsExtra = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[smsExtra.length];
nmessages = SmsHolder.getNumberUnreadSms(context) +1;
for (int i=0; i<msgs.length; i++)
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
//take out content from sms
String body = sms.getMessageBody().toString();
String address = sms.getOriginatingAddress();
messages += "SMS from " + address + " :\n";
messages += body + "\n";
putSmsToDatabase(sms, context );
}
//—display the new SMS message—
createNotification(SmsMessage.createFromPdu((byte[])smsExtra[0]), context);
updateActivity();
}
}
public void updateActivity(){
}
private void putSmsToDatabase( SmsMessage sms, Context context )
{
String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
// Create SMS row
ContentValues values = new ContentValues();
values.put("address", sms.getOriginatingAddress().toString() );
values.put("date", mydate);
values.put("body", sms.getMessageBody().toString());
// values.put( READ, MESSAGE_IS_NOT_READ );
// values.put( STATUS, sms.getStatus() );
// values.put( TYPE, MESSAGE_TYPE_INBOX );
// values.put( SEEN, MESSAGE_IS_NOT_SEEN );
}
private void createNotification(SmsMessage sms, Context context){
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String contentTitle;
if (nmessages < 2){
contentTitle = "SMS: " + ContactsInterface.getContactDisplayNameByNumber(sms.getOriginatingAddress(), context);
}else {
contentTitle = nmessages + " " + context.getResources().getString(R.string.new_messages);
}
// construct the Notification object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(contentTitle)
.setContentText(sms.getMessageBody())
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(getIconBitmap())
.setNumber(nmessages);
builder.setAutoCancel(true);
//(R.drawable.stat_sample, tickerText,
// System.currentTimeMillis());
// Set the info for the views that show in the notification panel.
//notif.setLatestEventInfo(this, from, message, contentIntent);
/*
// On tablets, the ticker shows the sender, the first line of the message,
// the photo of the person and the app icon. For our sample, we just show
// the same icon twice. If there is no sender, just pass an array of 1 Bitmap.
notif.tickerTitle = from;
notif.tickerSubtitle = message;
notif.tickerIcons = new Bitmap[2];
notif.tickerIcons[0] = getIconBitmap();;
notif.tickerIcons[1] = getIconBitmap();;
*/
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, Login.class);
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Ritardo in millisecondi
builder.setContentIntent(resultPendingIntent);
// Note that we use R.layout.incoming_message_panel as the ID for
// the notification. It could be any integer you want, but we use
// the convention of using a resource id for a string related to
// the notification. It will always be a unique number within your
// application.
nm.notify(R.drawable.ic_drawer, builder.build());
}
private Bitmap getIconBitmap() {
BitmapFactory f = new BitmapFactory();
return f.decodeResource(context.getResources(), R.drawable.ic_sms);
}
}
If you just need to do it for a specific amount of time, probably the easiest way is to use a handler and use a postDelayed(). Something like this:
// SLEEP 5 SECONDS HERE ...
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// createNotification(SmsMessage.createFromPdu((byte[])smsExtra[0]), context);
updateActivity();
}
}, 5000);
If you want to wait for another action, that's a bit more complicated.