Show a notification for missed VOIP calls - android

I did not find an answer to this question.
I have a VOIP application. I'm able to add a log about missed calls in the native call-log but the notification is not shown.
Is there a way to ask the device native call log to show the notification?
I would not like to add my own notification because I want to be sure that the icon is always that one that the native call-log application would show for other calls.
I found this but there is no answer.
I'm using a code that is similar to that one shown in the previous post.

Just for clarity:
You can still add your own notification, but use the android system build-in icons - these are the same icons that the built-in phonecall app is using. For example:
Notification notification = new Notification();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.icon = android.R.drawable.stat_notify_missed_call;
This way you will always display the icon that's characteristic for the specific Android OS version.
For more information check out the Icon Guidelines, and especially in your case -the status bar icons.

If you are just adding an entry in the call log db the notificatin will not be shown.
You need to add your on notification.
If you do not add your own notification, a notification will be shown only at phone start up if the call log is still there.

This is my implementation (mainly copied from the android code):
private static void showMissedCallNotification(Context context, final Contact contact) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// display the first line of the notification:
// 1 missed call: call name
// more than 1 missed call: <number of calls> + "missed calls"
int titleResId;
String expandedText;
numberMissedCalls++;
if (numberMissedCalls == 1) {
titleResId = R.string.notification_missedCallTitle;
expandedText = contact.getDisplayName();
} else {
titleResId = R.string.notification_missedCallsTitle;
expandedText = context.getString(R.string.notification_missedCallsMsg,
numberMissedCalls);
}
final PendingIntent callLogIntent = createCallLogIntent(context);
// make the notification
int id = android.R.drawable.stat_notify_missed_call;
String ticker = context.getString(R.string.notification_missedCallTicker, contact.getDisplayNumber());
long currentTime = Platform.timeProvider().getTime();
Notification note = new Notification(id, ticker, currentTime);
note.setLatestEventInfo(context, context.getText(titleResId), expandedText, callLogIntent);
note.flags |= Notification.FLAG_AUTO_CANCEL;
// This intent will be called when the notification is dismissed.
// It will take care of clearing the list of missed calls.
note.deleteIntent = createClearMissedCallsIntent(context);
//configureLedNotification(note);
notificationManager.notify(MISSED_CALL_NOTIFICATION, note);
}
/**
* Returns an intent to be invoked when the missed call notification is clicked.
* #param context
*/
private static PendingIntent createCallLogIntent(Context context) {
Intent intent = new Intent(context, ClearMissedCallsService.class);
intent.setAction(ClearMissedCallsService.ACTION_OPEN_CALL_LOGS);
return PendingIntent.getService(context, 0, intent, 0);
}
/**
* Returns an intent to be invoked when the missed call notification is cleared.
* #param context
*/
private static PendingIntent createClearMissedCallsIntent(Context context) {
Intent intent = new Intent(context, ClearMissedCallsService.class);
intent.setAction(ClearMissedCallsService.ACTION_CLEAR_MISSED_CALLS);
return PendingIntent.getService(context, 0, intent, 0);
}
/*package */ static void cancelMissedCallNotification() {
// reset the number of missed calls to 0.
numberMissedCalls = 0;
notificationManager.cancel(MISSED_CALL_NOTIFICATION);
}
and:
/**
* Handles the intent to clear the missed calls that is triggered when a notification is dismissed.
*/
public class ClearMissedCallsService extends IntentService {
/** This action is used to clear missed calls. */
public static final String ACTION_CLEAR_MISSED_CALLS = "com.android.phone.intent.CLEAR_MISSED_CALLS";
public static final String ACTION_OPEN_CALL_LOGS = "com.android.phone.intent.OPEN_CALL_LOGS";
public ClearMissedCallsService() {
super(ClearMissedCallsService.class.getSimpleName());
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
// Clear the list of new missed calls.
ContentValues values = new ContentValues();
values.put(Calls.NEW, 0);
StringBuilder where = new StringBuilder();
where.append(Calls.NEW);
where.append(" = 1 AND ");
where.append(Calls.TYPE);
where.append(" = ?");
getContentResolver().update(Calls.CONTENT_URI, values, where.toString(),
new String[]{ Integer.toString(Calls.MISSED_TYPE) });
NativeCallLog.cancelMissedCallNotification();
if (ACTION_OPEN_CALL_LOGS.equals(intent.getAction())) {
Intent intentOpenCallLogs = createOpenCallLogIntent();
startActivity(intentOpenCallLogs);
}
}
private static Intent createOpenCallLogIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW, null);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setType("vnd.android.cursor.dir/calls");
return intent;
}
}
you also need to add this in the AndroidManifest
<service
android:exported="true"
android:name="yourpackage.ClearMissedCallsService" >
<intent-filter >
<action android:name="com.android.phone.intent.CLEAR_MISSED_CALLS" />
</intent-filter>
<intent-filter >
<action android:name="com.android.phone.intent.OPEN_CALL_LOGS" />
</intent-filter>
</service>

Related

Notification Action without starting new Activity?

I plan to have a heads up notification that has two Actions: one to Approve a login request and one to Decline a login request. By clicking on either of these actions I wish to fire off a HTTP request to my server and most importantly do not want to start a new Activity or have the user redirected to my app at all.
Context context = getBaseContext();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.notificationicon)
.setContentTitle(notificationTitle)
.setContentText("Access Request for " + appName + " : " + otp)
.setDefaults(Notification.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.addAction(R.drawable.ic_tick, "Approve", someApproveIntent? );
Here is my notification builder and after looking around it seems that the addAction method is looking for a new/pendingIntent, which is confusing me as I cannot find any examples online where Intents do not lead to new Activities being fired off.
How would I implement some code (a method maybe) rather then starting a new Activity on each of my Actions?
If you don't want to start an activity you can also wrap a BroadcastReceiver or a Service directly in a PendingIntent.
Wherever you build your notification...
Your notification actions will start a service directly.
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)...
Intent iAction1 = new Intent(context, MyService.class);
iAction1.setAction(MyService.ACTION1);
PendingIntent piAction1 = PendingIntent.getService(context, 0, iAction1, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(iconAction1, titleAction1, piAction1);
// Similar for action 2.
MyService.java
IntentServices run in a row one after another. They do the work on a worker thread.
public class MyService extends IntentService {
public static final String ACTION1 = "ACTION1";
public static final String ACTION2 = "ACTION2";
#Override
public void onHandleIntent(Intent intent) {
final String action = intent.getAction();
if (ACTION1.equals(action)) {
// do stuff...
} else if (ACTION2.equals(action)) {
// do some other stuff...
} else {
throw new IllegalArgumentException("Unsupported action: " + action);
}
}
}
AndroidManifest.xml
Don't forget to register the service in manifest.
<manifest>
<application>
<service
android:name="path.to.MyService"
android:exported="false"/>
</application>
</manifest>

Android IntentService not completing task if App is closed

I'm using an IntentService to saveData to a SQLDatabase & upload data to Parse. The IntentService works fine if I keep the app running. It also executes propery if I minimise it(by pressing the home button).
But if I press the navigation button and destory the app(the thing where the app screen scales down and you swipe it off); then the IntentService stops running(it doesnt even call onDestory).
What I want is to have the service execute all the tasks; and destory itself. Hence, START_STICKY (Intent) is not required as I dont want it to run continuously in the background.
Starting IntentService
Intent intent_publishService = new Intent(getApplicationContext(), PublishService.class);
Bundle basket_storyData = new Bundle();
basket_storyData.putAll( packStoryData() );
intent_publishService.putExtra(KEY_BASKET_STORY_DATA, basket_storyData);
intent_publishService.putParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA, (ArrayList<? extends Parcelable>) final_image_data);
startService(intent_publishService);
PublishService.class (Snippet)
#Override
protected void onHandleIntent(Intent intent)
{
Log.i(TAG, "ONHANDLEINTENT" );
context = getApplicationContext();
final String KEY_BASKET_IMAGE_DATA = "key_basket_image_data";
final String KEY_BASKET_STORY_DATA = "key_basket_story_data";
final String KEY_BASKET_EXTRA = "key_basket_extra";
ArrayList<ImagesData> _iDataSave = new ArrayList<ImagesData>();
_iDataSave.addAll( (Collection<? extends ImagesData>) intent.getParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA) );
Log.i(TAG, "_iDataSize:" + Integer.toString(_iDataSave.size()) );
//Get Bundle Values
Bundle storyBundle = intent.getBundleExtra(KEY_BASKET_STORY_DATA);
publishStory(storyBundle, _iDataSave);
}
Edit1: Manifest Declaration
<service android:name="com.example.create.main.PublishService" />
SOLVED
You will need START_STICKY in this case to indicate to android that you wish to try to continue to do work after the app is killed.
When the user swipes away from the app chooser, that will kill the app process unconditionally. You can't prevent that from happening - it is intended to give the user control over what is running at that very moment.
Here's what needs to be done:
1) Change IntentService >> Service
2) Move all the code to onStartCommand
3) Using a separate thread so that everything is done off the UI-Thread
4) Declaring it as a separate process in the Manifest
PublishService.class (Snippet)
#Override
public int onStartCommand(final Intent intent, int flags, int startId)
{
Log.i(TAG, "ONSTARTCOMMAND" );
Intent notificationIntent = new Intent(this, MyFriendList_Activity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setAutoCancel(false);
builder.setTicker("this is ticker text");
builder.setContentTitle("WhatsApp Notification");
builder.setContentText("You have a new message");
builder.setSmallIcon(R.drawable.ic_launcher);
//builder.setContentIntent(pendingIntent);
builder.setOngoing(true);
builder.setNumber(100);
// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
builder.setProgress(0, 0, true);
Notification notificationFinal = builder.getNotification();
startForeground(ONGOING_NOTIFICATION_ID, notificationFinal );
Runnable r = new Runnable()
{
public void run()
{
context = getApplicationContext();
final String KEY_BASKET_IMAGE_DATA = "key_basket_image_data";
final String KEY_BASKET_STORY_DATA = "key_basket_story_data";
final String KEY_BASKET_EXTRA = "key_basket_extra";
ArrayList<ImagesData> _iDataSave = new ArrayList<ImagesData>();
_iDataSave.addAll( (Collection<? extends ImagesData>) intent.getParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA) );
Log.i(TAG, "_iDataSize:" + Integer.toString(_iDataSave.size()) );
//Get Bundle Values
Bundle storyBundle = intent.getBundleExtra(KEY_BASKET_STORY_DATA);
publishStory(storyBundle, _iDataSave);
}
};
Thread t = new Thread(r);
t.start();
//return START_STICKY;
//return START_REDELIVER_INTENT;
//return START_CONTINUATION_MASK;
return START_NOT_STICKY;
}
Manifest Declaration
<service
android:name="com.example.create.main.PublishService"
android:process=".publishservice" />
Concern
startForeground() + separate Process + running on a separate Thread
--- maybe all 3-are not required?
Edit 1: Also; you could skip all the foreground stuff; and return START_CONTINUATION_MASK ; but thats not recommended as every device has a different way of handling that return type

Android - Trouble with service sending multiple local notifications

I've inherited a code base for an Android app and I'm facing a particularly though problem with local notifications.
The idea is to send a notification for each event which is scheduled in the future, considering also the reminder preference on how many minutes before the event the user wants to be notified.
Everything works just fine, except that after the notification is thrown for the first time, if the user opens the app before the event starts, the notification gets thrown another time. This happens every time the app is opened between (event start date - reminder) and event start date.
I've already gave a look at this and also this with no luck.
I've read that using a service may cause exactly this problem and some suggest to remove it but I think this is needed since the notification must be thrown also when the app is closed.
Currently the structure of the code is the following:
Edit - updated description of TabBarActivity
Inside TabBarActivity I have the method scheduleTravelNotification that schedules the AlarmManager.
This method is executed everytime there is a new event to be added on local database, or if an existing event have been updated.
The TabBarActivity runs this method inside the onCreate and onResume methods.
TabBarActivity is also the target of the notification - onclick event.
private static void scheduleTravelNotification(Context context, RouteItem routeItem) {
long currentTime = System.currentTimeMillis();
int alarmTimeBefore = routeItem.getAlarmTimeBefore();
long alarmTime = routeItem.getStartTime() - (alarmTimeBefore * 1000 * 60);
if(alarmTimeBefore < 0){
return;
}
if(alarmTime < currentTime){
return;
}
Intent actionOnClickIntent = new Intent(context, TravelNotificationReceiver.class);
PendingIntent travelServiceIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis(), actionOnClickIntent, PendingIntent.FLAG_ONE_SHOT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(alarmTime);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), travelServiceIntent);
Log.e("NEXT ALARM", "Time: " + String.valueOf(calendar.getTimeInMillis()));
}
This is TravelNotificationReceiver.java (should I use LocalBroadcastReceiver instead of BroadcastReceiver?)
public class TravelNotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("RECEIVER", "received TravelNotification request");
Intent notificationIntent = new Intent(context, TravelNotificationService.class);
context.startService(notificationIntent);
}
}
TravelNotificationService.java extends NotificationService.java setting as type = "Travel", flags = 0, title = "something" and text = "something else".
public abstract class NotificationService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification();
return super.onStartCommand(intent, flags, startId);
}
public abstract String setNotificationType();
public abstract int setNotificationFlags();
public abstract String setNotificationTitle();
public abstract String setNotificationText();
/**
* Executes all the logic to init the service, prepare and send the notification
*/
private void sendNotification() {
int flags = setNotificationFlags();
String type = setNotificationType();
NotificationHelper.logger(type, "Received request");
// Setup notification manager, intent and pending intent
NotificationManager manager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intentAction = new Intent(this.getApplicationContext(), TabBarActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intentAction, flags);
// Prepares notification
String title = setNotificationTitle();
String text = setNotificationText();
Notification notification = NotificationHelper.buildNotification(getApplicationContext(), title, text, pendingIntent);
// Effectively send the notification
manager.notify(101, notification);
NotificationHelper.logger(type, "Notified");
}
}
Edit - Here's the code for NotificationHelper.buildNotification
public static Notification buildNotification(Context context, String title, String text, PendingIntent pendingIntent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setAutoCancel(true);
builder.setContentText(text);
builder.setContentTitle(title);
builder.setContentIntent(pendingIntent);
builder.setSmallIcon(R.mipmap.launcher);
builder.setCategory(Notification.CATEGORY_MESSAGE);
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
return builder.build();
}
Thank you for the answers!
Edit I've seen also this but has no accepted answers, while this post suggest something that I think it's already managed with if(alarmTime < currentTime){ return; } in scheduleTravelNotification.
This may not be your exact problem, but at a glance, you're sending the notification in onStartCommand() which can itself be run many times during the lifetime of the service -- for example, if you issue the service start command "blindly" in an onCreate of an activity, it will happen every time the activity is (re)created.
You have a few options for handling this.
One is to create a boolean flag as a property of the service, default to false, and check it before sending the notification. If it's false, send the notification and set it to true, and if it's already true you do not send a notification.
Another is to check and see if the service is already running, and if it is, don't send the service start command in the first place. This can be tedious to do everywhere, and violates DRY, so if you take this route you may want to create a static method in your service class which checks to see if the service is running and then starts it if not, and call that instead of explicitly starting the service.
Similar to user3137702 answer you could simple have a static boolean of APPISINFORGROUND which is checked everytime the send notification method is hit, and managed from your application/activities code.
As User said it is likely that your onStartCommand method is being called at odd times due to the app / service lifecycle.
Alternatively check your receiver is not being called somewhere else from your code.
It may be your NotificationHelper class which is causing an issue. Please share the code for this class.
One thought may be that your notification is not set to be auto cancelled, check if you include the setAutoCancel() method in your Notification Builder.
Notification notification = new Notification.Builder(this).setAutoCancel(true).build();
I've found a way to make it work, I'm posting this since it seems to be a problem of many people using the approach suggested in this and this articles. After months of testing I can say I'm pretty satisfied with the solution I've found.
The key is to avoid usage of Services and rely on AlarmScheduler and Receivers.
1) Register the receiver in your manifest by adding this line:
<receiver android:name="<your path to>.AlarmReceiver" />
2) In your activity or logic at some point you want to schedule a notification related to an object
private void scheduleNotification(MyObject myObject) {
// Cal object to fix notification time
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(myObject.getTime());
// Build intent and extras: pass id in case you need extra details in notification text
// AlarmReceiver.class will receive the pending intent at specified time and handle in proper way
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("OBJECT_ID", myObject.getId());
// Schedule alarm
// Get alarmManager system service
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(getBaseContext().ALARM_SERVICE);
// Build pending intent (will trigger the alarm) passing the object id (must be int), and use PendingIntent.FLAG_UPDATE_CURRENT to replace existing intents with same id
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), myObject.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Finally schedule the alarm
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
}
3) Define AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Find object details by using objectId form intent extras (I use Realm but it can be your SQL db)
MyObject myObject = RealmManager.MyObjectDealer.getObjectById(intent.getStringExtra("OBJECT_ID"), context);
// Prepare notification title and text
String title = myObject.getSubject();
String text = myObject.getFullContent();
// Prepare notification intent
// HomeActivity is the class that will be opened when user clicks on notification
Intent intentAction = new Intent(context, HomeActivity.class);
// Same procedure for pendingNotification as in method of step2
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(context, myObject.getId(), intentAction, PendingIntent.FLAG_UPDATE_CURRENT);
// Send notification (I have a static method in NotificationHelper)
NotificationHelper.createAndSendNotification(context, title, text, pendingNotificationIntent);
}
}
4) Define NotificationHelper
public class NotificationHelper {
public static void createAndSendNotification(Context context, String title, String text, PendingIntent pendingNotificationIntent) {
// Get notification system service
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
// Build notification defining each property like sound, icon and so on
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(text);
notificationBuilder.setSmallIcon(R.drawable.ic_done);
notificationBuilder.setCategory(Notification.CATEGORY_MESSAGE);
notificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setContentIntent(pendingNotificationIntent);
notificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
notificationManager.notify(1001, notificationBuilder.build());
}
}
At this point it should work and schedule / trigger notification at the right time, and when notification is opened it will appear only once starting the activity declared in notification pending intent.
There is still a problem, AlarmManager have a "volatile" storage on user device, so if user reboots or switch off the phone you will lose all intents that you previously scheduled.
But fortunately there is also a solution for that:
5) Add at top of your manifest this uses permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
6) Right below the line added at step 1 register the boot receiver
<receiver android:name="<your path to>.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
7) Define the BootReceiver
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do something very similar to AlarmReceiver but this time (at least in my case) since you have no source of intents loop through collection of items to understand if you need to schedule an alarm or not
// The code is pretty similar to step 3 but repeated in a loop
}
}
At this point your app should be able to schedule / trigger notification and restores those reminders even if the phone is switched off or rebooted.
Hope this solution will help someone!

How to know make notification when user doesn't executing application

I'd like to make an notification which start to count time when user exited android application. If user do not executed application after 1hours, It notified me to execute and If user ignoring it, It executes saved SMS messages. I found some examples on timer, but I do not know how to find application exit time. Please give me some advice with full code. I am desperately need it...
TimerTask task = new TimerTask(){
public void run() {
try {
mainTime++;
int min = mainTime / 60;
int sec = mainTime % 60;
String strTime = String.format("%s : %s", min, sec);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Timer mTimer = new Timer();
mTimer.schedule(task, 0, 60000);
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("Chack your app", smsBody);
sendIntent.putExtra("12345678", phonenumber);
sendIntent.setType("vnd.android-dir/mms-sms");
startActivity(sendIntent);
Okay so what you need to do is to store the system time locally (may be using SharedPreferences) when the application exits. You can register a BroadcastReceiver which will help you trigger some action when 1hr or a certain time has passed from the locally stored time when app exited.
If you want to know how to handle programmatically when and how to exit the app , please refer this answer.
You could also try to use the Android alarm system. Once the user exit your application, you could set up an Alarm. Something like:
YourActivityOrFragment.java
#Override
protected void onStop() {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
c.add(Calendar.HOUR,1);
scheduleAlarm(c.getTimeInMillis());
}
private void scheduleAlarm(long time) {
Intent yourIntent = new Intent("Some_ID");
PendingIntent pi = PendingIntent.getBroadcast(YourClass.this, ALARM_ID, yourIntent, PendingIntent.FLAG_CANCEL_CURRENT);
// Put some extras here, if you need so. Like:
// yourIntent.putExtra("field","value");
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,time,pi);
}
Now, create a BroadcastReceiver to handle those alarms.
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private static final String LOG_TAG = AlarmReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "Alarm fired!");
Intent it = new Intent(context, YourNotificationHandler.class);
// Get your Extras here. And do whatever you want, if you need.
// For what you said, there's no need to start an Activity, so let's handle that alarm as a service.
context.startService(it);
// But if for some reason you want to start an Activity, just do it like:
// context.startActivity(it);
}
}
On your AndroidManifest.xml declare your BroadcastReceiver.
<receiver android:name=".AlarmReceiver" >
<intent-filter>
<action android:name="Some_ID" />
<category android:name="android.intent.category.default" />
</intent-filter>
</receiver>
And last of all, create your service to handle your notifications, you could try something like an IntentService. On that file, you'll have a onHandleIntent(Intent intent) method. Get your Intent there, and it's Extras, and do whatever you want to do. Later, just call your Notifications. I've used a utility class on my projects to handle those, but feel free to choose how you'll do that.
Example:
public static void createService(Context context, CharSequence tickerMessage, CharSequence title,
CharSequence message, int icon, int id, Intent intent, long[] pattern, Boolean autoCancel) {
PendingIntent p = PendingIntent.getService(context, 0, intent, 0);
Notification n;
int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 11) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setTicker(tickerMessage)
.setContentText(message)
.setSmallIcon(icon)
.setContentIntent(p)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
if (pattern.length > 0) {
builder.setVibrate(pattern);
}
if (autoCancel != null) {
builder.setAutoCancel(autoCancel);
}
if (apiLevel >= 17) {
// Android 4.2+
n = builder.build();
}
else {
// Android 3.x
n = builder.getNotification();
}
}
else {
// Android 2.2+
n = new Notification(icon, tickerMessage, System.currentTimeMillis());
// Data
n.setLatestEventInfo(context, title, message, p);
}
NotificationManager nm = (NotificationManager)
context.getSystemService(Activity.NOTIFICATION_SERVICE);
nm.notify(id, n);
}
You can read more about alarms here.
More on Service here.
BroadcastReceiver here.
Notifications, here and here.
And this might be an interesting read about Notification as well.

How to stop Service Intent and cancel pending Notification

I have followed tutorial in http://developer.android.com/training/notify-user/index.html
It works well. But what I want is : when I click ping, the old service will we stopped, and then create the service again. So if I clicked id multiple time, It will notify me only once.
Problem: If I set time 10, then I click "Ping" button. Then after 5 second, I click it again. It will notify me twice.
What I want : If I set time 10, then I click "Ping" button. Then after 5 second, I click it it will notify only once, 10 secondds after the last time I click the button.
public class MainActivity extends Activity {
private Intent mServiceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Creates an explicit Intent to start the service that constructs and
// issues the notification.
mServiceIntent = new Intent(getApplicationContext(), PingService.class);
}
/*
* Gets the values the user entered and adds them to the intent that will be
* used to launch the IntentService that runs the timer and issues the
* notification.
*/
public void onPingClick(View v) {
stopCurrentService();
int seconds;
// Gets the reminder text the user entered.
EditText msgText = (EditText) findViewById(R.id.edit_reminder);
String message = msgText.getText().toString();
mServiceIntent.putExtra(CommonConstants.EXTRA_MESSAGE, message);
mServiceIntent.setAction(CommonConstants.ACTION_PING);
Toast.makeText(this, R.string.timer_start, Toast.LENGTH_SHORT).show();
// The number of seconds the timer should run.
EditText editText = (EditText) findViewById(R.id.edit_seconds);
String input = editText.getText().toString();
if (input == null || input.trim().equals("")) {
// If user didn't enter a value, sets to default.
seconds = R.string.seconds_default;
} else {
seconds = Integer.parseInt(input);
}
int milliseconds = (seconds * 1000);
mServiceIntent.putExtra(CommonConstants.EXTRA_TIMER, milliseconds);
// Launches IntentService "PingService" to set timer.
startService(mServiceIntent);
}
private void stopCurrentService() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
.getRunningServices(Integer.MAX_VALUE);
if (serviceList.size() <= 0) { }
int size = serviceList.size();
for (int i = 0; i < size; i++) {
RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if (serviceName.getClassName().equals(PingService.class.getName())) {
try {
Intent intentstop = new Intent();
intentstop.setComponent(serviceName);
getApplicationContext().stopService(intentstop);
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
}
}
PingService creates a notification that includes 2 buttons: one to snooze the
notification, and one to dismiss it.
public class PingService extends IntentService {
private NotificationManager mNotificationManager;
private String mMessage;
private int mMillis;
NotificationCompat.Builder builder;
private boolean status;
public PingService() {
// The super call is required. The background thread that IntentService
// starts is labeled with the string argument you pass.
super("com.example.android.pingme");
}
#Override
protected void onHandleIntent(Intent intent) {
// The reminder message the user set.
mMessage = intent.getStringExtra(CommonConstants.EXTRA_MESSAGE);
// The timer duration the user set. The default is 10 seconds.
mMillis = intent.getIntExtra(CommonConstants.EXTRA_TIMER,
CommonConstants.DEFAULT_TIMER_DURATION);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String action = intent.getAction();
// This section handles the 3 possible actions:
// ping, snooze, and dismiss.
if (action.equals(CommonConstants.ACTION_PING)) {
issueNotification(intent, mMessage);
} else if (action.equals(CommonConstants.ACTION_SNOOZE)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.snoozing));
// Sets a snooze-specific "done snoozing" message.
issueNotification(intent, getString(R.string.done_snoozing));
} else if (action.equals(CommonConstants.ACTION_DISMISS)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
}
}
private void issueNotification(Intent intent, String msg) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Sets up the Snooze and Dismiss action buttons that will appear in the
// expanded view of the notification.
Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
PendingIntent piDismiss = PendingIntent.getService(this, 0,
dismissIntent, 0);
Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
PendingIntent piSnooze = PendingIntent.getService(this, 0,
snoozeIntent, 0);
// Constructs the Builder object.
builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setTicker("Ping ! ping ! PIng!")
.setContentTitle(getString(R.string.notification))
.setContentText(getString(R.string.ping))
.setDefaults(Notification.DEFAULT_ALL)
// requires VIBRATE permission
/*
* Sets the big view "big text" style and supplies the text (the
* user's reminder message) that will be displayed in the detail
* area of the expanded notification. These calls are ignored by
* the support library for pre-4.1 devices.
*/
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.addAction(R.drawable.ic_stat_dismiss,
getString(R.string.dismiss), piDismiss)
.addAction(R.drawable.ic_stat_snooze,
getString(R.string.snooze), piSnooze);
/*
* Clicking the notification itself displays ResultActivity, which
* provides UI for snoozing or dismissing the notification. This is
* available through either the normal view or big view.
*/
Intent resultIntent = new Intent(this, ResultActivity.class);
resultIntent.putExtra(CommonConstants.EXTRA_MESSAGE, msg);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Because clicking the notification opens a new ("special") activity,
// there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
startTimer(mMillis);
}
// Starts the timer according to the number of seconds the user specified.
private void startTimer(int millis) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_start));
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.sleep_error));
}
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_finished));
issueNotification(builder);
}
private void issueNotification(NotificationCompat.Builder builder) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Including the notification ID allows you to update the notification
// later on.
mNotificationManager.notify(CommonConstants.NOTIFICATION_ID,
builder.build());
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
I have called stopService(), but the old notification shows up again.
What I want is it will notify me once, 10 seconds after the latest click.
You can use handler in order to stop/start your service.
Please look at my code. It's not exactly related to your code but you can get the idea.
Click this link
You can do checking in Run method of Runnable.

Categories

Resources