为什么警报通知没有显示?

时间:2015-03-22 21:05:07

标签: android android-intent android-activity alarmmanager android-pendingintent

在我的闹钟项目中,我添加了pendingIntent。我希望当警报触发时,它应该能够弹出通知消息(以便用户知道警报正在触发),即使应用程序已关闭/最小化/或设备处于空闲状态。但即使我有ComponentName,我的情况也不会发生这种情况。此时,要停止闹钟,我必须再次打开应用程序并关闭切换按钮。 (1) 我该如何解决?

正如我所说,一旦应用程序关闭/或最小化,我需要重新打开应用程序以停止警报。但如果我按下切换按钮停止,它不会停止报警。我切换越多,它通过相同的铃声循环越多并加快音调,这是非常非常有线的。 (2)为什么会发生这种情况以及如何解决? [注意:当应用程序已经打开时,它不会发生,这只发生在我关闭/最小化/或返回。]

我使用了set方法。这个问题是警报也可以在过去的时间设置中触发。但是,这个我有点不想要的东西。 (3)可以解决此问题的set()替代方法是什么?

[P.S。我知道这是一个很大的帖子,对某人来说可能是令人厌恶的。我的谦虚请求,不要评论负面或沮丧我的帖子。如果你真的不喜欢我,并且不想采取任何步骤来帮助我,简单地避免发布。我正在通过这个闹钟APP获得如此多的讽刺和痴迷。]

MainActivity:

package com.mycompany.alarmclock;

import android.support.v7.app.ActionBarActivity;
//imported stuff isn't shown here.
public class MainActivity extends Activity {

    AlarmManager alarmManager;
    private PendingIntent pendingIntent;//an action to be performed by other/foreign application
    private TimePicker alarmTimePicker;//In where the user set the time
    private static MainActivity inst;
    private TextView alarmTextView;//the area where alarm message/notification will be displayed


    public static MainActivity instance() {
        return inst;
    }

    public void onStart() {
        super.onStart();
        inst = this;
    }

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

        alarmTimePicker = (TimePicker) findViewById(R.id.alarmTimePicker);
        alarmTextView = (TextView) findViewById(R.id.alarmText);
        ToggleButton alarmToggle = (ToggleButton) findViewById(R.id.alarmToggle);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    }


    public void onToggleClicked(View view) {
        if (((ToggleButton) view).isChecked()) {//if toggle button is "ON" do the alarming function
            Log.d("MainActivity", "Alarm On");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, alarmTimePicker.getCurrentHour());
            calendar.set(Calendar.MINUTE, alarmTimePicker.getCurrentMinute());
            Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
            pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
            alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);

        } else {
            AlarmReceiver.stopRingtone();
            alarmManager.cancel(pendingIntent);
            setAlarmText("");
            Log.d("MyActivity", "Alarm Off");
        }

    }

    public void setAlarmText(String alarmText) {
        alarmTextView.setText(alarmText);

    }

}

AlarmReceiver:

    package com.mycompany.alarmclock;

import android.support.v4.content.WakefulBroadcastReceiver;
//Imported stuff isn't shown here
public class AlarmReceiver extends WakefulBroadcastReceiver {

    private static Ringtone mRingtone=null;
    @Override
    public void onReceive(final Context context, Intent intent) {

        MainActivity inst=MainActivity.instance();
        inst.setAlarmText("\n                  Alarm!\n           Get Up! Get up!");
        Uri alarmUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);

        if (alarmUri == null) {
            alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        }
        Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
        mRingtone=RingtoneManager.getRingtone(context,alarmUri);
        mRingtone.play();
        //ringtone.play();

        ComponentName comp = new ComponentName(context.getPackageName(),
                AlarmService.class.getName());
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
    public  static void stopRingtone(){
        mRingtone.stop();
    }
}

AlarmService:

    package com.mycompany.alarmclock;
//imported stuff isn't shown here.
import android.support.v4.app.NotificationCompat;
public class AlarmService extends IntentService {

private NotificationManager alarmnotificationManager;

    public AlarmService(){
        super("AlarmService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        sendNotification("Get up! Get up!");

    }
    private void sendNotification(String msg){

        Log.d("AlarmService","Sending notification...:"+msg);
        alarmnotificationManager=(NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        NotificationCompat.Builder alamNotificationBuilder = new NotificationCompat.Builder(
                this).setContentTitle("Alarm").setSmallIcon(R.drawable.ic_launcher)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText(msg);


        alamNotificationBuilder.setContentIntent(contentIntent);
        alarmnotificationManager.notify(1, alamNotificationBuilder.build());
        Log.d("AlarmService", "Notification sent.");

    }

}

activity_mail.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" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
    android:background="#deb887">



    <TimePicker
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/alarmTimePicker"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:background="#8ffdba" />


    <ToggleButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Alarm On/Off"
    android:id="@+id/alarmToggle"
    android:layout_centerHorizontal="true"
    android:layout_below="@+id/alarmTimePicker"
    android:onClick="onToggleClicked"
        android:checked="false"
        android:background="#000000"
        android:focusable="true"
        android:textColor="#f3f6ff"
        android:textSize="25dp"
        android:textStyle="bold"
        android:layout_marginTop="15dp" />



    <TextView
        android:layout_width="258dp"
        android:layout_height="match_parent"

        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text=""
        android:id="@+id/alarmText"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/alarmToggle"
        android:background="#0e8146"
        android:layout_marginBottom="80dp"
        android:textColor="#ff0000" />

    <Button
        style="?android:attr/buttonStyleSmall"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:text="Share On Facebook"
        android:id="@+id/button"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="#3B5998"
        android:layout_marginBottom="10dp"
        android:focusable="true"
        android:shadowColor="#b0e0e6"
        android:textColor="#00ff80"
        android:textStyle="bold" />

</RelativeLayout>

AndroidManifest:

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


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


    <application

        android:allowBackup="true"
        android:icon="@drawable/icon_updated"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".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>
        <receiver android:name="AlarmReceiver"/>
    </application>

</manifest>

更新: LOG:

  03-23 15:28:46.372    1474-1474/com.mycompany.alarmclock I/System.out﹕ debugger has settled (1321)
03-23 15:28:46.548    1474-1474/com.mycompany.alarmclock D/libEGL﹕ loaded /system/lib/egl/libEGL_genymotion.so
03-23 15:28:46.548    1474-1474/com.mycompany.alarmclock D/﹕ HostConnection::get() New Host Connection established 0xb7ddaf88, tid 1474
03-23 15:28:46.560    1474-1474/com.mycompany.alarmclock D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_genymotion.so
03-23 15:28:46.560    1474-1474/com.mycompany.alarmclock D/libEGL﹕ loaded /system/lib/egl/libGLESv2_genymotion.so
03-23 15:28:46.604    1474-1474/com.mycompany.alarmclock W/EGL_genymotion﹕ eglSurfaceAttrib not implemented
03-23 15:28:46.608    1474-1474/com.mycompany.alarmclock E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from GradienCache
03-23 15:28:46.608    1474-1474/com.mycompany.alarmclock E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 8192
03-23 15:28:46.616    1474-1474/com.mycompany.alarmclock E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from Caches::initConstraints()
03-23 15:28:46.616    1474-1474/com.mycompany.alarmclock E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 8192
03-23 15:28:46.616    1474-1474/com.mycompany.alarmclock D/OpenGLRenderer﹕ Enabling debug mode 0

2 个答案:

答案 0 :(得分:1)

使用setExact()代替set(),使用RTC_WAKEUP代替RTC,可以解决问题1和问题3。

请参阅setExactRTC_WAKEUP的文档。

关于过去设置的闹钟,这是set()

的设计

文档说明:

  

如果声明的触发时间是过去的,则会立即触发警报。如果已安排此Intent的警报(两个意图的相等性由filterEquals(Intent)定义),则它将被删除并替换为此。

另见帖子:Android AlarmManager: how to avoid to going off of past alarms

现在,对于您最大的问题,问题2,它似乎是由于您没有IntentPendingIntent设置正确取消警报,如果该应用已关闭并重新开放。

此外,您可能希望添加PendingIntent.FLAG_UPDATE_CURRENT作为额外的故障保护,以防止多个警报被安排。

见下面的代码:

 public void onToggleClicked(View view) {
        if (((ToggleButton) view).isChecked()) {//if toggle button is "ON" do the alarming function
            Log.d("MainActivity", "Alarm On");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, alarmTimePicker.getCurrentHour());
            calendar.set(Calendar.MINUTE, alarmTimePicker.getCurrentMinute());
            Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
            pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);

        } else {
            AlarmReceiver.stopRingtone();

            Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
            pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

            alarmManager.cancel(pendingIntent);
            setAlarmText("");
            Log.d("MyActivity", "Alarm Off");
        }

    }

答案 1 :(得分:1)

我想在问题#2中帮助你。我相信你说切换按钮可以启动和停止闹钟定时器。但是当你关闭或最小化时它不起作用,我称之为&#34;撤消后台堆栈&#34;返回屏幕。我希望我的问题是正确的。

现在......我不喜欢(不舒服)放置new Intent的地方,因为Pending Intent可能会失去其原始背景,我相信。所以将下面的代码放在/移动到onToggleClicked()的 OnCreate 中,也许在底部是可以的:

Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);

我主要担心的是,当你取消()来自set()的对象时,我想确保对象 pendingIntent 是相同的。要明确的是,上面的代码不应该在onToggleClicked上了,我的建议。