0

I am developing an App where I need to run a background service every 3 minutes to fetch some data in JSON format from the server.

Right now, for testing purposes, I am trying to hit the service to show the notification every 30 seconds. But strangely, it invokes the service and show the notification 3-4 times only and stop showing any further notifications afterward.

I am using AlarmManager to achieve this task.

MainActivity

    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;

    import com.google.android.material.tabs.TabLayout;

    import androidx.viewpager.widget.ViewPager;
    import androidx.appcompat.app.AppCompatActivity;

    import android.util.Log;

    import com.matrix.msnimble.service.CaseReceiver;
    import com.matrix.msnimble.ui.main.SectionsPagerAdapter;

    public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
            ViewPager viewPager = findViewById(R.id.view_pager);
            viewPager.setAdapter(sectionsPagerAdapter);
            TabLayout tabs = findViewById(R.id.tabs);
            tabs.setupWithViewPager(viewPager);

            Intent caseReceiver = new Intent(getApplicationContext(), CaseReceiver.class);
            PendingIntent recurringCaseReceiver = PendingIntent.getBroadcast(getApplicationContext(), 0, caseReceiver, PendingIntent.FLAG_CANCEL_CURRENT);
            AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            alarms.setInexactRepeating (AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 30000, recurringCaseReceiver);
        }
    }

BroadcastReceiver

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

public class CaseReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent pushPullService = new Intent(context, PushPullService.class);
        context.startService(pushPullService);
    }
}

Service

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import com.matrix.msnimble.MainActivity;
import com.matrix.msnimble.R;

public class PushPullService extends IntentService {

    public PushPullService() {
        super(PushPullService.class.getName());
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        createNotificationChannel();
        showNotification();
    }

    private void showNotification(){

        Intent intent = new Intent(this.getApplicationContext(), MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intent, 0);
        Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.icon );

        Notification builder = new NotificationCompat.Builder(this.getApplicationContext(), "casenotification")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle("New Case(s)")
                .setContentText("You have received 5 fresh cases")
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setDefaults(Notification.DEFAULT_ALL)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setLargeIcon(largeIcon)
                .setAutoCancel(true).build();
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this.getApplicationContext());

        try {
            int max = 10000;
            int min = 1;
            int range = max - min + 1;

            notificationManager.notify((int)(Math.random() * range) + min, builder);
        }catch
        (Exception e){Log.d("--->",e.getMessage());}
    }

    private void createNotificationChannel() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "casenotification";
            String description = "com.matrix.msnimble";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel("casenotification", name, importance);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC );
            channel.setDescription(description);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

AndroidManifest

<service
    android:name=".service.PushPullService"
    android:enabled="true"
    android:exported="true">
</service>
<receiver android:name=".service.CaseReceiver" ></receiver>

Notification's Screenshot on Device

enter image description here

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
maddy23285
  • 738
  • 6
  • 16
  • give the unique notificationId for the each and individual notification. – Harish Reddy Oct 21 '19 at 06:26
  • Could you suggest any ways to do this for testing purposes? Right now I am relying upon Math.random() and hoping to get a unique number in return. Will subsequent notification fails, once the system gets a duplicate id from the same app? – maddy23285 Oct 21 '19 at 06:28

2 Answers2

1

Please follow this link to generate notification, give the unique notificationId for the each and individual notification

Harish Reddy
  • 922
  • 10
  • 20
  • Same issue. Stopped after 4 notifications. It starts again only after launching MainActivity manually. But again stops after a few notifications. Tested on 2 devices but the problem is the same. I logged notification id to check and it is generated fine. I am getting different id every time. – maddy23285 Oct 21 '19 at 06:51
1

Try this intent service class for your continuous Notification and API call with some duration basis. And one thing you have set startForeground for continuous notification and make alive your service. I hope it will help you.

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import com.matrix.msnimble.MainActivity;
import com.matrix.msnimble.R;

public class PushPullService extends IntentService {
    private Handler mhandler;
    private long mDelay = 500; //Default 500ms delay
    private Runnable mrunnable;
    private int NOTIFICATION_ID = 0;

     private Notification makeNotification(Context context) {
       Intent intent = new Intent(this.getApplicationContext(), MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intent, 0);
    Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.icon );

        String channelId = getString(R.string.channel_name);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId)
                        .setContentTitle("New Case(s)")
                        .setContentText("You have received 5 fresh cases")
            .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .setLargeIcon(largeIcon)
                        .setContentIntent(pendingIntent)
                        .setAutoCancel(false);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

       // Since android Oreo notification channel is needed.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId,
                    getString(R.string.app_name),
                    NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
        }
        Notification n;
        n = notificationBuilder.build();
        return n;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    mhandler = new Handler();
        int delay = 10000; //milliseconds : you can set as per your requirement
        mrunnable = new Runnable() {
            @Override
            public void run() {
                //TODO: Your API call or whatever you want call that method
                mhandler.postDelayed(this, delay);
            }
        };
        mhandler.postDelayed(mrunnable, delay);

        startForeground(1, makeNotification(this));

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager != null)
            notificationManager.cancel(NOTIFICATION_ID);
        stopForeground(true);
        if (mhandler != null)
            mhandler.removeCallbacks(mrunnable);
    }
}
Koushik Mondal
  • 865
  • 7
  • 15
  • Thanks for the reply, but I switched to a firebase jobdispatcher to resolve this issue. Actually I don't want to implement foreground notification. Moreover, my background service should run even if the app itself is not running. Something like Whatsapp message notifications. I basically want to synchronize SQLite DB with the server's DB and after completion of sync, it should notify the user about the newly added records and no notification if there are no new records. – maddy23285 Oct 21 '19 at 10:57