问题
Currently I have a requirement that enables push notifications in the app but we can't use other APIs like google's Firebase. So we have the handle the notification management by ourselves.
I have thought of this (its just a draft, sorry if there are some typos or mistakes):
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;
}
}
}
This service every X number of seconds makes a server call to see if there are notifications available for the user, if any are found then it is build with the NotificationBuilder, its actions are created and then it is shown to the user.
Making the service call the server at such a low intervals will hit the performance of the app. I think that using Service instead of the IntentService would achieve the same result. What are your comments about this? Is there a better way to achieve this or a cleaner solution?
回答1:
You need to generate notification from app. (with alarm manager at specific time)
Add in 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>
SplashScreen (Activity)
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();
}
}
来源:https://stackoverflow.com/questions/48199362/custom-notification-center