2 Stimmen

Android AlarmManager plant zufällig Benachrichtigungen?

Ich versuche, eine Erinnerungsanwendung zu erstellen, die eine Erinnerung in der Statusleiste einblendet. Wie ich verstehe, ist der Android NotificationManager das Standardwerkzeug, um Benachrichtigungen zu planen, aber ein BootService wird benötigt, um Benachrichtigungen neu zu planen, da geplante Ereignisse nicht über Boote hinweg überleben.

Im Folgenden habe ich eine Anwendung zusammengestellt, die beim Hochfahren eine einzelne Erinnerung einplant und eine Benachrichtigung in der Statusleiste einblendet. Wenn Sie auf die Benachrichtigung klicken, wird die MainActivity gestartet, die in Zukunft Optionen zum Hinzufügen weiterer Erinnerungen, zum Löschen von Erinnerungen oder Ähnlichem haben wird.

Das Problem, das ich habe, ist, dass die Erinnerung beim ersten Mal richtig funktioniert, aber sie scheint sich neu zu planen und aus irgendeinem Grund zu zufälligen Zeiten wieder aufzutauchen. Sollte ich eine andere Aktivität als diejenige starten, die den BootAlarmService installiert?

UPDATE: Ich glaube, ich habe mit logcat einige Hinweise gefunden. Anscheinend stürzt der Dienst ab und wird neu gestartet, wodurch die Benachrichtigung zurückgesetzt wird. Irgendwelche Ideen, warum das so ist?

UPDATE II : Code auf Arbeitsmodell geändert

ActivityManager   I  No longer want com.example.alarm_boot_test (pid 1428): hidden #16
ActivityManager   W  Scheduling restart of crashed service com.example.alarm_boot_test/.BootAlarmService in 5000ms
ActivityManager   W  Scheduling restart of crashed service com.example.alarm_boot_test/.NotificationAlarmService in 15000ms
ActivityManager   I  Start proc com.example.alarm_boot_test for service com.example.alarm_boot_test/.BootAlarmService: pid=2321 uid=10069 gids={}
       dalvikvm   D  Debugger has detached; object registry had 1 entries
        szipinf   D  Initializing inflate state
BootAlarmService  D  oncreate()
BootAlarmService  D  alarm set for Thu Jan 17 08:03:00 CST 2013

MainActivity.java

package com.example.alarm_boot_test;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity
{

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

}

BootAlarmService.java

package com.example.alarm_boot_test;

import java.util.Calendar;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class BootAlarmService extends Service
{
    private final String TAG = this.getClass ().getName ();

    @Override
    public void onCreate ()
    {
        Log.d (TAG, "oncreate()");
        super.onCreate ();
    }

   @Override
   public int onStartCommand (Intent intent, int flags, int startId)
   {
       Log.d (TAG, "alarm_test: BootAlarmService.onStartCommand() Received start id " + startId + ": " + intent);

       // if intent == null, service has been killed/restarted by system
       if (intent != null)
        createNotificationOnBoot();
       else
        Toast.makeText (getBaseContext (), "Intent was null in BootAlarmService.", Toast.LENGTH_LONG).show();

       return START_STICKY;
    }

    private void createNotificationOnBoot ()
    {
        Intent inotify = new Intent(this , NotificationAlarmService.class);
        inotify.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
        AlarmManager amgr = (AlarmManager)getSystemService(ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, inotify, 0);

        // go off two mins from now
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, calendar.get (Calendar.MINUTE) + 2);

        amgr.set (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis (), pendingIntent);

        Log.d (TAG, "alarm set for " + calendar.getTime ().toString ());
    }

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

}

BootReceiver.java

package com.example.alarm_boot_test;

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

public class BootReceiver extends BroadcastReceiver
{

    @Override
    public void onReceive (final Context context, final Intent bootintent)
    {
        Intent i = new Intent ();
        i.setAction ("com.example.alarm_boot_test.BootAlarmService");
        context.startService (i);
    }

}

NotificationAlarmService.java

package com.example.alarm_boot_test;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class NotificationAlarmService extends Service
{
    private final String TAG = this.getClass().getName ();

    @Override
    public void onCreate ()
    {
        super.onCreate ();
    }

    @Override
    public int onStartCommand (Intent intent, int flags, int startId)
    {
       Log.d (TAG, "alarm_test: NotificationAlarmService.onStartCommand()");
       if (intent != null)
          createNotification ();
       else
          Toast.makeText (getBaseContext (), "Intent was null in NotificationAlarmService.", Toast.LENGTH_LONG).show();

       return super.onStartCommand (intent, flags, startId);
     }

    private void createNotification()
    {
      NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
      Notification notification = new Notification(android.R.drawable.stat_sys_warning, "Note from AlarmService", System.currentTimeMillis());
      Intent i = new Intent(this, ViewReminder.class);
      PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);

      notification.setLatestEventInfo(this, "New Notification", "You have been notified by AlarmService", pendingIntent);
      notificationManager.notify(10001, notification);

   }

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

*activity_main.xml*

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Service started! Reboot!" />

</RelativeLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarm_boot_test"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="9" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service android:name="com.example.alarm_boot_test.BootAlarmService" >
            <intent-filter>
                <action android:name="com.example.alarm_boot_test.BootAlarmService" >
                </action>
            </intent-filter>
        </service>

        <receiver android:name="com.example.alarm_boot_test.BootReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" >
                </action>
            </intent-filter>
        </receiver>

        <service android:name="com.example.alarm_boot_test.NotificationAlarmService" >
        </service>

        <activity
            android:name="com.example.alarm_boot_test.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

1voto

wufoo Punkte 12105

Für den Fall, dass es jemand anderem hilft, denke ich, dass ich den übergebenen Intent in der onStartCommand()-Methode sowohl in BootAlarmService.java als auch in NotificationAlarmService.java auf NULL überprüfen musste. Ich habe es erst ein paar Tage getestet, aber es sieht so aus, als ob das Intent NULL ist, wenn das System den Dienst beendet/neu startet. Durch einfaches Testen konnte ich die Benachrichtigung nur erstellen, wenn der Dienst zur Boot-Zeit gestartet wird (wenn das übergebene Intent NICHT null ist).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X