Android IntentService not completing task if App is closed - android

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

Related

Cannot keep android service alive after app is closed

I am trying to spawn a service that stays alive all the time, even if the user closes the application. According to these threads
Keep location service alive when the app is closed
Android Service Stops When App Is Closed
Android: keep Service running when app is killed
this can be accomplished with IntentServices or Service.START_STICKY
Yet, I tried both types of services without success. In other words, my services get killed when the app is closed by the user. Can someone point out if this is can be done and how? Here is what I have tried without success:
With IntentService:
public class MyIntentService extends IntentService {
private final int mPollingTimeMS = 500;
private int mInitializationPollingCount = 0;
private Thread mPollThread;
public MyIntentService() {
super("MyIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
mPollThread = new Thread() {
public void run() {
while (true) {
try {
Log.e(Constants.Engine.LOGGER_TAG_DEV,
"SDK Service Running: " +
mInitializationPollingCount * mPollingTimeMS +
"ms have elapsed");
mInitializationPollingCount++;
sleep(mPollingTimeMS);
} catch (Exception e) {
StackTraceElement trace = new Exception().getStackTrace()[0];
Logger.e(Constants.Engine.LOGGER_TAG_APP, "[Exception:" + e.toString() + "]" +
trace.getClassName() + "->" + trace.getMethodName() + ":" + trace.getLineNumber());
}
}
}
};
mPollThread.start();
}
}
and with Services:
public class MyService extends Service {
public MyService() {
}
private final int mPollingTimeMS = 500;
private int mInitializationPollingCount = 0;
private Thread mPollThread;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPollThread = new Thread() {
public void run() {
while (true) {
try {
Log.e(Constants.Engine.LOGGER_TAG_DEV,
"SDK Service Running: " +
mInitializationPollingCount * mPollingTimeMS +
"ms have elapsed");
mInitializationPollingCount++;
sleep(mPollingTimeMS);
} catch (Exception e) {
StackTraceElement trace = new Exception().getStackTrace()[0];
Logger.e(Constants.Engine.LOGGER_TAG_APP, "[Exception:" + e.toString() + "]" +
trace.getClassName() + "->" + trace.getMethodName() + ":" + trace.getLineNumber());
}
}
}
};
mPollThread.start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// I tried to return null here, but this
// service gets killed no matter what.
return null;
}
}
and here is the manifest:
<service
android:name=".mycompany.MyService"
android:enabled="true"
android:exported="true"
android:process=":process1">
</service>
<service
android:name=".mycompany.MyIntentService"
android:process=":process2"
android:exported="false">
</service>
I shall added that I am closing the test app not with a close button, but using the Android OS app manager. See picture below
Lastly, the driver activity (not much there)
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent1 = new Intent(getBaseContext(), MyService.class);
startService(intent1);
Intent intent2 = new Intent(getBaseContext(), MyIntentService.class);
startService(intent2);
}
}
I also try to add a notification and make it a foreground service but still the same thing. The moment I close the app, everything gets killed. This is what I added:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
showNotification();
...etc..
private void showNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
int iconId = R.mipmap.ic_launcher;
int uniqueCode = new Random().nextInt(Integer.MAX_VALUE);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(iconId)
.setContentText("Context Text")
.setContentIntent(pendingIntent).build();
startForeground(uniqueCode, notification);
}
Here is an example of foreground service that I use and that works, it remains active when the app is closed. Of course, it also must be started, and for that task the app must be running at a first glance, or a receiver of a boot event must be set, but this is another story.
public class MyService extends Service {
static final int NOTIFICATION_ID = 543;
public static boolean isServiceRunning = false;
#Override
public void onCreate() {
super.onCreate();
startServiceWithNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction().equals(C.ACTION_START_SERVICE)) {
startServiceWithNotification();
}
else stopMyService();
return START_STICKY;
}
// In case the service is deleted or crashes some how
#Override
public void onDestroy() {
isServiceRunning = false;
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
// Used only in case of bound services.
return null;
}
void startServiceWithNotification() {
if (isServiceRunning) return;
isServiceRunning = true;
Intent notificationIntent = new Intent(getApplicationContext(), MyActivity.class);
notificationIntent.setAction(C.ACTION_MAIN); // A string containing the action name
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentPendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.my_icon);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText(getResources().getString(R.string.my_string))
.setSmallIcon(R.drawable.my_icon)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(contentPendingIntent)
.setOngoing(true)
// .setDeleteIntent(contentPendingIntent) // if needed
.build();
notification.flags = notification.flags | Notification.FLAG_NO_CLEAR; // NO_CLEAR makes the notification stay when the user performs a "delete all" command
startForeground(NOTIFICATION_ID, notification);
}
void stopMyService() {
stopForeground(true);
stopSelf();
isServiceRunning = false;
}
}
Then I run it with
Intent startIntent = new Intent(getApplicationContext(), MyService.class);
startIntent.setAction(C.ACTION_START_SERVICE);
startService(startIntent);
Please note the two constants used as Actions, these are Strings that must start with the package name.
IntentService
Using IntentService is probably not the best approach. By default IntentService stops itself after onHandleIntent(Intent) returns and there's no work left to do (i.e. the request queue is empty). This is explained in the official docs of IntentService:
When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().
In your case, onHandleIntent(Intent) creates a thread but returns right away, which makes it stop by itself.
Service + startForeground()
Using a regular Service in foreground mode should work as long as you keep that service running on a separate process. For that, you need:
Make the onStartCommand() return START_STICKY.
Call the method to show the notification right in onCreate().
Run the service in a separate process (using android:process=":something").
Based on the post, it seems that you've tried some of these steps in isolation but never tried all of them at the same time.
If none of the answers above are working, maybe it is a manufacturer specific issue. Some MI phones, for instance, kill the foreground service when the user kill the app via task manager.
I recommend you to test the app on a virtual device, so you can check if it is or isn't this kind of issue.
Hope it helps!
You can simply call your service in your onStop() method inside your activity.
Even when user stops the app the service will still be running.
Try the answers for this similar question: Bad notification for startForeground in Android app

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.

Android Notifications from AI in background

I'm building a prototype application of a larger system. This prototype will be offline but still look like it's getting information from a server. Even when the app is not open (using DeamonThread).
So I created the Android application and now trying to add an AI (within the app) that create and delete tasks. It works, but when I try to add Notifications from the DeamonThread it won't since Thread is not an Activity.
I tried to change it to
extends Activity implements Runnable
But then it's not possible to make it Deamon.
Feels like I'm missing something easy..
public void run() {
while (counter < 100) {
try {
sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
Task task = new Task("AI", "this was the " + counter
+ " AI message", flow);
sendNotation();
}
counter++;
}
}
private void sendNotation() {
NotificationManager nm=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent intent = new Intent(this, Flippin.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
String body = "This is a message from Adam";
String title = "One new Task";
NotificationCompat.Builder n = new NotificationCompat.Builder(this);
n.setContentIntent(pi);
n.setSmallIcon(R.drawable.notif);
n.setContentTitle(title);
n.setContentText(body);
n.setDefaults(Notification.DEFAULT_ALL);
n.setAutoCancel(true);
nm.notify(uniqueID, n.build());
finish();
}
If you want to start a daemon, then you should look at Service
There are many tutorials out there for sending notification from Service.
And yes, it is possible to send notification from non-UI thread, using Handler.
This is the solution I was looking for, only thing I needed was to get access to the context (my application). NOTE I do believe this is a bad design, but since this is used only for a prototype I'll see it as perfect.
In Android Manifest file declare following
<application android:name="com.example.MyApplication">
</application>
then write the class
public class MyApplication extends Application{
private static Context context;
public void onCreate(){
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Now every where call MyApplication.getAppContext() to get your application context statically.
private void sentNotation() {
NotificationManager nm = (NotificationManager) MyApplication.getAppContext().getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(MyApplication.getAppContext(), Flippin.class);
PendingIntent pi = PendingIntent.getActivity(MyApplication.getAppContext(), 0, intent, 0);
String body = "This is a message from Adam";
String title = "One new Task";
NotificationCompat.Builder n = new NotificationCompat.Builder(MyApplication.getAppContext());
n.setContentIntent(pi);
n.setSmallIcon(R.drawable.notif);
n.setContentTitle(title);
n.setContentText(body);
n.setDefaults(Notification.DEFAULT_ALL);
n.setAutoCancel(true);
nm.notify(uniqueId, n.build());
finish();
}

Android: Start Intent from any screen

I want to open a screen when a particular event occurs, regardless of the screen where I am now, how do I do that?
Intent Iatualizar = new Intent(this, Atualizar.class);
startActivity(Iatualizar);
The above code works if I'm with the screen open the program, but not work when the screen was in the background. How to make it work? thank you
Add FLAG_ACTIVITY_NEW_TASK to your Intent. If you check the log cat, it will also tell you this.
You should just create a service that loads your activity when the event happens.
To do this, you can start the service when your application is loaded, and have your event receiver in your service class. This way, even if other applications are running and your application is not in the foreground (showing on the screen) you will still be able to trigger off the event.
Android garbage collection will try to kill off your activity if it isn't in the foreground and you start running low on resources.
If you want to go a step further and make the service a foreground service, then it will theoretically be the last thing that Android will kill when it is running low on memory. Let me know if you need a code example.
Hopefully this helps you!
Cheers
-- EDIT --
Here is a code example to get you started.
In your activities onCreate call some code similar to what you have above to launch your service.
ie:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent IatualizarService = new Intent(this, AtualizarService.class);
startService(Iatualizar);
}
You could also have this in your onResume if you want, (or start it from a button, or however you want this service to start).
Then create a service class like so:
public class AtualizarService extends Service {
private final IBinder mBinder = new MyBinder();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onCreate() {
// In here you can make your service a foreground service to help prevent garbage collection from occurring.
makeforeground();
}
private boolean makeforeground() {
String msg = "Turning on foreground service";
ErrorLog.i(getApplicationContext(), TAG, msg);
try {
Notification notification = new Notification(
R.drawable.ic_dialog_info,
getText(R.string.notification_text),
System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent activityIntent = new Intent(this, YourMainActivity.class);
activityIntent.setAction(Intent.ACTION_MAIN);
activityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
activityIntent, 0);
notification.setLatestEventInfo(this,
getText(R.string.notification_title),
getText(R.string.notification_text), pendingIntent);
startForeground(1234567890, notification); // random id
return true;
} catch (Exception e) {
String error = "displayNotification Error Message: "
+ e.getMessage() + " Cause: " + e.getCause();
ErrorLog.e(GlobalParameters.getContext(),
TAG + " Notification Foreground Service", error);
return false;
}
}
#Override
public void onDestroy() {
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyBinder extends Binder {
AtualizarService getService() {
return AtualizarService .this;
}
}
}
Then inside this service class, you can add in a broadcast receiver that can trigger on any event you want. And then load up your activity if you want it to.
Cheers
Try this, you can also start a service using the code below
Intent Iatualizar = new Intent(this, Atualizar.class);
Iatualizar.addFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(Iatualizar);

Show a notification for missed VOIP calls

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>

Categories

Resources