Search code examples
androidandroid-notificationsandroid-handlerandroid-looper

How can I trigger my notification from a method?


I am trying to trigger my notification bottom. I followed this example code http://www.compiletimeerror.com/2013/10/status-bar-notification-example-in.html#.VWtoS1xViko

I can trigger the notification when I call the method from my HomeActivity which is my main activity for the app. When try to call from one of the methods within the app, nothing happens. (eg)

HomeActivity homeactivity = new HomeActivity();
homeactivity.Notify("Title: ...", "Msg: ... ");

Here are the logs for the event. I trigger an alert after 5 button presses

05-31 18:33:41.533  10118-10118/com.myapp.md E/>>>>>>﹕ MultiClickEvent clickCount = 5
05-31 18:33:41.543  10118-10118/com.myapp.md E/>>>>>>>﹕ in onActivation of HWReceiver
05-31 18:33:41.603  10118-10118/com.myapp.md V/Vibrator﹕ Called vibrate(long) API - PUID: 10588, PackageName: com.myapp.md
05-31 18:33:41.603  10118-10118/com.myapp.md V/Vibrator﹕ vibrate - PUID: 10588, PackageName: com.myapp.md, ms: 3000, mag: -1
05-31 18:33:41.643  10118-10118/com.myapp.md D/AbsListView﹕ onVisibilityChanged() is called, visibility : 4
05-31 18:33:41.643  10118-10118/com.myapp.md D/AbsListView﹕ unregisterIRListener() is called
05-31 18:33:41.643  10118-10118/com.myapp.md D/AbsListView﹕ onVisibilityChanged() is called, visibility : 4
05-31 18:33:41.643  10118-10118/com.myapp.md D/AbsListView﹕ unregisterIRListener() is called
05-31 18:33:41.643  10118-11068/com.myapp.md E/>>>>>>﹕ in CurrentLocationProvider CONSTRUCTOR - trying to retrieve location from getLastKnownLocation()
05-31 18:33:41.833  10118-11068/com.myapp.md I/com.myapp.md.alert.SMSAdapter﹕ Sms sent: I need IMMEDIATE help! - I'm here https://maps.google.com/maps?q=40.7348922,-73.977548 via network
05-31 18:33:44.883  10118-10118/com.myapp.md E/>>>>>>>﹕ in onReceive of HWReceiver
05-31 18:33:44.883  10118-10118/com.myapp.md E/>>>>>>>﹕ in onReceive of HWReceiver context com.myapp.md.trigger.HardwareTriggerService@429b89b0
05-31 18:33:44.883  10118-10118/com.myapp.md E/>>>>>>>﹕ in onReceive of HWReceiver intent Intent { act=android.intent.action.SCREEN_ON flg=0x50000010 }

I tried to put the notification in my SMSAdapter

public class SMSAdapter {
    private static final String LOG_TAG = SMSAdapter.class.getName();

    public void sendSMS(Context context, String phoneNumber, String message) {
//        Log.e("20140411", "sending fake SMS -> " + message);
        if(!ApplicationSettings.isFirstMsgSent(context)){
            ApplicationSettings.setFirstMsgSent(context, true);
        }
        SmsManager smsManager = getSmsManager();
        try {
            smsManager.sendTextMessage(phoneNumber, null, message, null, null);
            Log.i(LOG_TAG, "Sms sent: " + message);
            HomeActivity homeactivity = new HomeActivity();
            homeactivity.Notify("Title: Text SOS",
                    "Msg: Alerting your emergency contacts ");
        } catch (Exception exception) {
            Log.e(LOG_TAG, "Sending SMS failed " + exception.getMessage());
        }
    }

    SmsManager getSmsManager() {
        return SmsManager.getDefault();
    }
}

When I do that I get this message

05-31 18:39:33.163  18640-19982/com.textsosalert.md E/>>>>>>﹕ in CurrentLocationProvider CONSTRUCTOR - trying to retrieve location from getLastKnownLocation()
05-31 18:39:33.383  18640-19982/com.textsosalert.md I/com.textsosalert.md.alert.SMSAdapter﹕ Sms sent: I need IMMEDIATE help! - I'm here https://maps.google.com/maps?q=40.7348689,-73.9775756 via network
05-31 18:39:33.383  18640-19982/com.textsosalert.md E/com.textsosalert.md.alert.SMSAdapter﹕ Sending SMS failed Can't create handler inside thread that has not called Looper.prepare()

Here is the Notify method I defined:

@SuppressWarnings("deprecation")
public void Notify(String notificationTitle, String notificationMessage) {
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    @SuppressWarnings("deprecation")
    Notification notification = new Notification(R.drawable.icon_sos,
            "New Message", System.currentTimeMillis());

    Intent notificationIntent = new Intent(this, HomeActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);

    notification.setLatestEventInfo(HomeActivity.this, notificationTitle,
            notificationMessage, pendingIntent);
    notificationManager.notify(9999, notification);
}

Solution

  • The problem is that you're calling new HomeActivity(), which is something you should never do. Activities in Android are always started using startActivity() or startActivityForResult(), and should never be created explicitly with new.

    When you call new HomeActivity(), none of the Activity lifecycle callbacks are called, thus the Activity will not have a valid Context.

    So, this just won't work:

    HomeActivity homeactivity = new HomeActivity();
    homeactivity.Notify("Title: ...", "Msg: ... ");
    

    If you want to have a method that you can re-use in different places in your code, put it in separate class, and have the method take a Context as a parameter.

    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    
    public class MyNotification {
    
        @SuppressWarnings("deprecation")
        public static void notify(Context context, String notificationTitle, String notificationMessage) {
            NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            @SuppressWarnings("deprecation")
            Notification notification = new Notification(R.drawable.icon_sos,
                    "New Message", System.currentTimeMillis());
    
            Intent notificationIntent = new Intent(context, HomeActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                    notificationIntent, 0);
    
            notification.setLatestEventInfo(context, notificationTitle,
                    notificationMessage, pendingIntent);
            notificationManager.notify(9999, notification);
        }
    }
    

    Then in SMSAdapter, you would have:

        try {
            smsManager.sendTextMessage(phoneNumber, null, message, null, null);
            Log.i(LOG_TAG, "Sms sent: " + message);
            /* Don't do this:
            HomeActivity homeactivity = new HomeActivity();
            homeactivity.Notify("Title: Text SOS",
                    "Msg: Alerting your emergency contacts ");
            */
    
            //Do this instead:
            MyNotification.notify(context, "Title: Text SOS",
                    "Msg: Alerting your emergency contacts ");
    
        } catch (Exception exception) {
            Log.e(LOG_TAG, "Sending SMS failed " + exception.getMessage());
        }
    

    Also note that you can call this from HomeActivity using this as the context:

     MyNotification.notify(this, "Title: Text SOS",
                    "Msg: Alerting your emergency contacts ");