Search code examples
androidandroid-notifications

NotificationManager.notify locks the phone and Emulator


PROBLEM:

The phone/emulator locks up on repeated Notification updates. The only way to get the emulator back responsive after it gets locked is by pressing Home => Menu => Lock => Home => Menu Button in that given order.

CODE:

Notification pushing code:

        // Set up notifcation views
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); // Get notification manager
        RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.service_notification);
        contentView.setViewVisibility(R.id.current_error_text, View.GONE);
        contentView.setViewVisibility(R.id.error_text, View.GONE);
        contentView.setViewVisibility(R.id.info_error_text, View.GONE);
        contentView.setViewVisibility(R.id.info_text, View.GONE);
        contentView.setViewVisibility(R.id.next_check_in_text, View.VISIBLE);
        contentView.setViewVisibility(R.id.current_profile_text, View.VISIBLE);
        contentView.setViewVisibility(R.id.profile_name_text, View.VISIBLE);
        contentView.setTextViewText(R.id.next_check_in_text, mainText);
        // Set profile text now
        contentView.setTextViewText(R.id.profile_name_text, miniText);
        // Set up a new notification
        Notification notif = new Notification(R.drawable.service_logo_small, "Service is running", System.currentTimeMillis());
        notif.contentView = contentView; // Set content view
        // Create and plug in the PendingIntent
        Intent notifIntent = new Intent(this, EntryPointActivity.class);
        PendingIntent pIntent = PendingIntent.getActivity(this, 0, notifIntent, 0); // Set up the Pending Intent
        notif.contentIntent = pIntent;
        // Now set up notification flags
        notif.flags |= Notification.FLAG_NO_CLEAR;
        notif.flags |= Notification.FLAG_ONGOING_EVENT;
        notif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
        if(sp.getBoolean("UpdateLights", true)) notif.flags |= Notification.DEFAULT_LIGHTS;
        if(sp.getBoolean("UpdateVibrate", true)) notif.flags |= Notification.DEFAULT_VIBRATE;
        if(sp.getBoolean("UpdateSound", true)) notif.flags |= Notification.DEFAULT_SOUND;

        notificationManager.notify(R.string.app_name, notif);

All objects exist and the project compiles perfectly. I encounter NO NullPointerExceptions!

Code calling the notification creating function:

final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
@Override
public void run() {
    if(( nextUpdateIn - System.currentTimeMillis() ) > 0) {
        long milliseconds = (nextUpdateIn - System.currentTimeMillis());
        int seconds = (int) (milliseconds / 1000) % 60 ;
        int minutes = (int) ((milliseconds / (1000*60)) % 60);
        String toShow = "Next Check In: " + minutes + " minute" + ((minutes != 1) ? "s" : "") + " " + seconds + " second" + ((seconds != 1) ? "s" : "");
        pushNotification(STATE_LOADEDSUCCESSFULLY, currentProfile.getProfileName(), toShow);
    } else {
        currentState = STATE_RELOADING;
        pushNotification(STATE_RELOADING, null, "Refreshing..");
        timer.cancel();
    }
}
}, 1, 999);

Again, all objects exist! The notification IS UPDATED in the above process but it locks up BOTH THE EMULATOR AND PHONE as mentioned above!

AIM:

To update notification in the Status Bar to basically show a countdown till the next refresh.

EDIT:

I'm trying to run this code via a SERVICE and I've tried on emulators running Android 2.2, 2.3.3, 4.1 and all of them give me the same problem!


Solution

  • Well, I finally figured what the problem is.

    You may be interested in this link too: http://code.google.com/p/android/issues/detail?id=13941#c12

    So, according to the above link, I stopped create a new Notification object everytime the notification pushing function is called. Now, I create the object once and keep reusing it! This has stopped the emulator lock ups!

    Following is the modification to the Notification pushing code:

        // Set up notifcation views
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.service_notification);
        contentView.setViewVisibility(R.id.current_error_text, View.GONE);
        contentView.setViewVisibility(R.id.error_text, View.GONE);
        contentView.setViewVisibility(R.id.info_error_text, View.GONE);
        contentView.setViewVisibility(R.id.info_text, View.GONE);
        contentView.setViewVisibility(R.id.next_check_in_text, View.VISIBLE);
        contentView.setViewVisibility(R.id.current_profile_text, View.VISIBLE);
        contentView.setViewVisibility(R.id.profile_name_text, View.VISIBLE);
        contentView.setTextViewText(R.id.next_check_in_text, mainText);
        // Set profile text now
        contentView.setTextViewText(R.id.profile_name_text, miniText);
        // Set up a new notification
        notif.contentView = contentView; // Set content view
        // Create and plug in the PendingIntent
        Intent notifIntent = new Intent(this, EntryPointActivity.class);
        PendingIntent pIntent = PendingIntent.getActivity(this, 0, notifIntent, 0); // Set up the Pending Intent
        notif.contentIntent = pIntent;
        // Now set up notification flags
        notif.flags |= Notification.FLAG_NO_CLEAR;
        notif.flags |= Notification.FLAG_ONGOING_EVENT;
        notif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
        if(sp.getBoolean("UpdateLights", true)) notif.flags |= Notification.DEFAULT_LIGHTS;
        if(sp.getBoolean("UpdateVibrate", true)) notif.flags |= Notification.DEFAULT_VIBRATE;
        if(sp.getBoolean("UpdateSound", true)) notif.flags |= Notification.DEFAULT_SOUND;
    
        notificationManager.notify(R.string.app_name, notif);
    

    You'd probably be seeing that the NotificationManager and Notification are no longer being created in the notification pushing code.

    Following are the changes I made to the timer:

    NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); // Get notification manager
    Notification notif = new Notification(R.drawable.service_logo_small, "Service is running", System.currentTimeMillis());
    final Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask(){
    @Override
    public void run() {
        if(( nextUpdateIn - System.currentTimeMillis() ) > 0) {
            long milliseconds = (nextUpdateIn - System.currentTimeMillis());
            int seconds = (int) (milliseconds / 1000) % 60 ;
            int minutes = (int) ((milliseconds / (1000*60)) % 60);
            String toShow = "Next Check In: " + minutes + " minute" + ((minutes != 1) ? "s" : "") + " " + seconds + " second" + ((seconds != 1) ? "s" : "");
            pushNotification(STATE_LOADEDSUCCESSFULLY, currentProfile.getProfileName(), toShow);
        } else {
            currentState = STATE_RELOADING;
            pushNotification(STATE_RELOADING, null, "Refreshing..");
            timer.cancel();
        }
    }
    }, 1, 999);
    

    As you may be seeing, I reuse the object notificationManager and notif in the timer and thus the CPU is not burdened to re-create the Notification object every time the Timer is being executed.

    So, with the above code changes my code now works perfectly!

    Thanks for helping me.