在我的闹钟项目中,我添加了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
答案 0 :(得分:1)
使用setExact()
代替set()
,使用RTC_WAKEUP
代替RTC
,可以解决问题1和问题3。
请参阅setExact和RTC_WAKEUP的文档。
关于过去设置的闹钟,这是set()
。
文档说明:
如果声明的触发时间是过去的,则会立即触发警报。如果已安排此Intent的警报(两个意图的相等性由filterEquals(Intent)定义),则它将被删除并替换为此。
另见帖子:Android AlarmManager: how to avoid to going off of past alarms
现在,对于您最大的问题,问题2,它似乎是由于您没有Intent
和PendingIntent
设置正确取消警报,如果该应用已关闭并重新开放。
此外,您可能希望添加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上了,我的建议。