java - 没有 GCM 的 Android 推送通知可以在后台服务中工作,但推送通知会在预计时间之前显示

标签 java android notifications android-service android-broadcastreceiver

我创建了一个 Android 应用程序,它可以每五分钟显示一次推送通知。我已经为此应用程序添加了一些特别的内容。这可以在应用程序关闭时显示推送通知。这意味着这是在后台服务上运行的。

此外,这可以在设备重新启动时显示通知。所有这些过程应该每五分钟后运行一次。但是,这个通知显示的时间早于预计的时间。

注意

我的应用程序没有使用 GCM。

这是我使用的步骤,

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver{
    private int MID = 0;
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Intent notificationIntent = new Intent(context, MainActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);


        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(
                context).setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Alaram Fired")
                .setContentText("Events To be PErformed").setSound(alarmSound)
                .setAutoCancel(true).setWhen(when)
                .setContentIntent(pendingIntent)
                .setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
        notificationManager.notify(MID, mNotifyBuilder.build());
        MID++;

    }
}

MyService.java

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Let it continue running until it is stopped.
        Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();


        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        intent = new Intent(MyService.this, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(MyService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager) MyService.this.getSystemService(MyService.this.ALARM_SERVICE);
        am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 5, pendingIntent);

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
    }

}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.context=this;
    }

    public void startService(View view) {
        startService(new Intent(getBaseContext(), MyService.class));
    }

    // Method to stop the service
    public void stopService(View view) {
        stopService(new Intent(getBaseContext(), MyService.class));
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.agent_app.mynotification">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service android:name=".MyService"/>
        <receiver android:name="com.agent_app.mynotification.AlarmReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

每五分钟后我应该做什么才能使这项工作正常进行?

有什么想法吗?

谢谢。

最佳答案

这是因为操作系统以这样的方式安排来自各种应用程序的警报调用,即对设备的唤醒调用最少,从而最大限度地减少电池消耗。建议报警频率尽可能低,防止电池耗尽(不少于30分钟)。

来自文档,

Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.

引用this完整详细信息的链接。

关于java - 没有 GCM 的 Android 推送通知可以在后台服务中工作,但推送通知会在预计时间之前显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37700925/

相关文章:

java - 在 Android 上使用按钮 - 新手

安卓 : Open Multiple Chat Window for different users

java - 如何在状态栏中获得永久应用程序通知程序?

java - 使用 printf 处理多种格式

java - 使用 thymeleaf、Spring Boot 获取复选框列表的值

java - 在 Quarkus 中使用 ResourceLoader

java - Android 9 Api 28 通知未显示

java - 在 Java 中使用静态内部类作为 POJO 是一个好主意吗

android - Calabash-android 与 Crosswalk v10.39.235.15

java - ListView 适配器返回错误的项目