自定义通知中心

Posted

技术标签:

【中文标题】自定义通知中心【英文标题】:Custom Notification Center 【发布时间】:2018-01-11 03:29:23 【问题描述】:

目前我有一个要求在应用程序中启用推送通知,但我们不能使用其他 API,如谷歌的 Firebase。所以我们自己处理通知管理。

我想到了这个(这只是一个草稿,如果有错别字或错误,请见谅):

public class MyNotificationCenter extends IntentService
    private static final String TAG = MyNotificationCenter.class.getSimpleName();
    private Timer GetNotifications;
    private long INTERVAL_REQUEST = 20000;
    private boolean isBusy = false;

    public MyNotificacionCenter()
        super("MyNotificationCenter");
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
        StartGetNotifications();
        return START_NOT_STICKY;
    

    @Override
    protected void onHandleIntent(Intent intent)

    

    @Override
    public void OnDestroy()
        super.onDestroy();
        StopGettingNotifications();
    

    private void StartGetNotifications()
        StopGettingNotifications();
        GetNotifications = new Timer();
        GetNotifications.schedule(new QueryNotificationTask,0,INTERVAL_REQUEST);
    

    private void StopGettingNotifications()
        if (GetNotifications != null)
            GetNotifications.cancel();
            GetNotifications.purge();
            GetNotifications = null;
        
    

    private class QueryNotificationTask extends TimerTask

        @Override
        public void run()
            GetNotifications();
        
    

    void GetNotifications()
        if (isBusy) return;
        isBusy = true;
        try
            /*Service calls that checks if notifications are available for the user
             *and updates data if required*/
        catch(Exception e)
            /*Save or show the exception in the log*/
        finally 
            isBusy = false;
        
    

此服务每 X 秒调用一次服务器,以查看是否有可供用户使用的通知,如果找到,则使用 NotificationBuilder 构建它,创建其操作,然后将其显示给用户。

让服务以如此短的间隔调用服务器会影响应用的性能。我认为使用 Service 而不是 IntentService 会达到相同的结果。 您对此有何看法? 有没有更好的方法来实现这一目标或更清洁的解决方案?

【问题讨论】:

【参考方案1】:

您需要从应用程序生成通知。 (与警报管理器在 具体时间)

在 manifest.xml 中添加

<uses-permission android:name="android.permission.WAKE_LOCK" />

<service
            android:name=".LocalNotificationIntentService"
            android:enabled="true"
            android:exported="false"/>

<receiver
            android:name=".OnBootBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
</receiver>     

启动画面(活动)

onCreate()

    LocalNotificationEventReceiver.setupAlarm(getApplicationContext());

OnBootBroadcastReceiver.class

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class OnBootBroadcastReceiver extends BroadcastReceiver 
    @Override
    public void onReceive(Context context, Intent intent) 
        LocalNotificationEventReceiver.setupAlarm(context);
    

LocalNotificationEventReceiver.class

public class LocalNotificationEventReceiver extends WakefulBroadcastReceiver 

    private static final String ACTION_START_NOTIFICATION_SERVICE = "ACTION_START_NOTIFICATION_SERVICE";
    private static final String ACTION_DELETE_NOTIFICATION = "ACTION_DELETE_NOTIFICATION";

    public static void setupAlarm(Context context) 
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent alarmIntent = getStartPendingIntent(context);


        Calendar calendar = Calendar.getInstance();
        Calendar setCalendar = Calendar.getInstance();
        setCalendar.set(Calendar.HOUR_OF_DAY, 7);
        setCalendar.set(Calendar.MINUTE, 30);
        setCalendar.set(Calendar.SECOND, 0);

        if (setCalendar.before(calendar))
            setCalendar.add(Calendar.DATE, 1);

        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                setCalendar.getTimeInMillis(),
                AlarmManager.INTERVAL_DAY,
                alarmIntent);


        /*long firstRunTime = calendar.getTimeInMillis();
        long futureInMillis = 60 * 1000;
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                firstRunTime,
                futureInMillis,
                alarmIntent);*/

    

    @Override
    public void onReceive(Context context, Intent intent) 
        String action = intent.getAction();
        Intent serviceIntent = null;
        if (ACTION_START_NOTIFICATION_SERVICE.equals(action)) 
            serviceIntent = LocalNotificationIntentService.createIntentStartNotificationService(context);
         else if (ACTION_DELETE_NOTIFICATION.equals(action)) 
            serviceIntent = LocalNotificationIntentService.createIntentDeleteNotification(context);
        

        if (serviceIntent != null) 
            startWakefulService(context, serviceIntent);
        
    

    private static PendingIntent getStartPendingIntent(Context context) 
        Intent intent = new Intent(context, LocalNotificationEventReceiver.class);
        intent.setAction(ACTION_START_NOTIFICATION_SERVICE);
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    

    public static PendingIntent getDeleteIntent(Context context) 
        Intent intent = new Intent(context, LocalNotificationEventReceiver.class);
        intent.setAction(ACTION_DELETE_NOTIFICATION);
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    

LocalNotificationIntentService.class

import android.app.ActivityManager;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.text.html;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class LocalNotificationIntentService extends IntentService 

    private static final int NOTIFICATION_ID = 1;
    private static final String ACTION_START = "ACTION_START";
    private static final String ACTION_DELETE = "ACTION_DELETE";
    static private int myUserSelectedSortedType = CommonUtils.SORT_BY_CUSTOMER_NAME;

    public LocalNotificationIntentService() 
        super(LocalNotificationIntentService.class.getSimpleName());
    

    public static Intent createIntentStartNotificationService(Context context) 
        Intent intent = new Intent(context, LocalNotificationIntentService.class);
        intent.setAction(ACTION_START);
        return intent;
    

    public static Intent createIntentDeleteNotification(Context context) 
        Intent intent = new Intent(context, LocalNotificationIntentService.class);
        intent.setAction(ACTION_DELETE);
        return intent;
    

    @Override
    protected void onHandleIntent(Intent intent) 
        try 
            String action = intent.getAction();
            if (ACTION_START.equals(action)) 
                processStartNotification();
            
            if (ACTION_DELETE.equals(action)) 
                processDeleteNotification(intent);
            
         finally 
            WakefulBroadcastReceiver.completeWakefulIntent(intent);
        
    

    private void processDeleteNotification(Intent intent) 
        // Log something?
    

    private void processStartNotification(Intent intent) 
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        Notification notification = getNotification(thePremiumReminderCount, theReminderDate, toYear);
        notificationManager.notify(NOTIFICATION_ID, notification);
    
    private Notification getNotification() 
        boolean isActivityFound = false;

        ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);

        List<ActivityManager.RunningTaskInfo> services = activityManager
                .getRunningTasks(Integer.MAX_VALUE);

        if (services.get(0).topActivity.getPackageName().toString()
                .equalsIgnoreCase(this.getPackageName().toString())) 
            isActivityFound = true;
        
        Intent openIntent = null;

        PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
                openIntent, PendingIntent.FLAG_ONE_SHOT);

        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                        .setDefaults(Notification.DEFAULT_ALL)
                        .setVibrate(new long[]100, 250, 100, 250, 100, 250)
                        .setAutoCancel(true)
                        .setColor(this.getResources().getColor(R.color.activity_toolbar_color))
                        .setContentTitle("title")
                        .setStyle(new NotificationCompat.BigTextStyle()
                                .bigText(Html.fromHtml("text")))
                        .setPriority(Notification.PRIORITY_MAX)
                        .setContentText(Html.fromHtml("text"));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            mBuilder.setSmallIcon(R.drawable.notification_icon1);
         else 
            mBuilder.setSmallIcon(R.drawable.notification_icon);
        
        mBuilder.setContentIntent(contentIntent);
        mBuilder.setDeleteIntent(LocalNotificationEventReceiver.getDeleteIntent(this));
        return mBuilder.build();
    
    

【讨论】:

以上是关于自定义通知中心的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中自定义通知区域

为啥 Galaxy S21 没有自定义通知声音

如何获取所有应用程序的所有通知都运行自定义通知

Appcelerator Titanium 中的自定义通知视图

自定义通知托盘不适用于某些手机

ios 的 FCM 自定义通知