【发布时间】:2020-11-29 19:14:44
【问题描述】:
我是 Android SDK 的新手,我开发了一个使用 AlarmManager 每 30 分钟发送一次通知的应用程序。每个通知都包含一个操作按钮。在 MainActivity 中,我有一个 TextView,其中显示了一个数字,用于计算操作按钮被点击的次数。
存在显示计数不正确的用例。要重现该问题,我执行以下步骤:
- 应用已最小化,我等待通知。
- 点击操作按钮
- 点击通知转到应用程序
应用程序会自行打开,但 TextView 仍显示“0”(就像在初始状态下一样)。但是,当我单击设备上的 BACK 按钮时,计数变为正确的计数。
当我点击通知时,我收到一条警告,这可能是问题的原因:
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@c8e60ce
我试图用 MainActivity 的 onCreate() 方法中的这一行来解决这个问题:
mCount.setText(String.valueOf(mCorrectPostureReceiver.getCount()));
但它不起作用。
我还应该提到,当我单击操作按钮,然后使用启动器(而不是通过点击通知)转到应用程序时,一切正常。
MainActivity.java
//
//imports
//
public class MainActivity extends AppCompatActivity {
private static final String LOG_TAG = MainActivity.class.getSimpleName();
private static String CORRECT_POSTURE_COUNT;
private NotificationManager mNotifyManager;
private static final int NOTIFICATION_ID = 0;
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private CorrectPostureReceiver mCorrectPostureReceiver = new CorrectPostureReceiver(this);
static final String POSTURE_YES_ACTION = BuildConfig.APPLICATION_ID + ".POSTURE_YES_ACTION";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createNotificationChannel();
ToggleButton mNotifToggle = findViewById(R.id.notify_toggle);
TextView mCount = findViewById(R.id.txt_count);
mCount.setText(String.valueOf(mCorrectPostureReceiver.getCount())); //doesn't work
//set alarmPendingIntent to deliver repeating notifications
final AlarmManager mAlarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
mNotifToggle.setChecked(PendingIntent.getBroadcast(this, NOTIFICATION_ID, alarmIntent, PendingIntent.FLAG_NO_CREATE) != null); // check if notifications were turned on before the new MainActivity was stopped
final PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_ID, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
registerReceiver(mCorrectPostureReceiver, new IntentFilter(POSTURE_YES_ACTION));
mNotifToggle.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String toastMessage = "error: AlarmManager is null";
if(isChecked) {
long repeatInterval;
//is emulator or device
if(Build.FINGERPRINT.startsWith("google/sdk_gphone_x86/generic")) {
repeatInterval = 30000; //short interval only for debug }
else { repeatInterval = AlarmManager.INTERVAL_HALF_HOUR; }
long triggerTime = SystemClock.elapsedRealtime() + repeatInterval;
if(mAlarmManager!=null) {
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, repeatInterval, alarmPendingIntent);
toastMessage = "Upright notifications on.";
}
}
else {
mNotifyManager.cancelAll();
if (mAlarmManager!=null) {
mAlarmManager.cancel(alarmPendingIntent);
}
toastMessage = "Upright notifications off.";
}
Toast.makeText(MainActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
}
}
);
Log.d(LOG_TAG, "A: created");
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
// super.onRestoreInstanceState(savedInstanceState); //should be commmented?
mCorrectPostureReceiver.getTxtCount().setText(savedInstanceState.getString(CORRECT_POSTURE_COUNT));
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putString(CORRECT_POSTURE_COUNT, String.valueOf(mCorrectPostureReceiver.getCount()));
super.onSaveInstanceState(outState);
}
private void createNotificationChannel() {
mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
long[] vibPattern = {0, 200, 200, 200, 200, 200}; //{delay1, vibDuration1, delay2, vibDuration2...}
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(
PRIMARY_CHANNEL_ID,
"Check posture notification",
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription("notification check posture");
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(vibPattern);
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
}
AlarmReceiver.java - 从 AlarmManager 接收重复的意图消息并传递通知
//
//imports
//
public class AlarmReceiver extends BroadcastReceiver {
private NotificationManager mNotificationManager;
private static final int NOTIFICATION_ID = 0;
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private static final String LOG_TAG = AlarmReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
deliverNotification(context);
Log.d(LOG_TAG, "notification fired!");
}
private void deliverNotification(Context context) {
//this intent causes that when the notification is clicked, the MainActivity is launched
Intent notifClickIntent = new Intent(context, MainActivity.class); //when the notification is clicked, the MainActivity is launched
PendingIntent notifClickPendingIntent = PendingIntent.getActivity(
context,
NOTIFICATION_ID,
notifClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// after you click the action button on notification, this intent will be sent
Intent postureYesIntent = new Intent(MainActivity.POSTURE_YES_ACTION);
PendingIntent yesPendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID, postureYesIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, PRIMARY_CHANNEL_ID)
.setContentTitle("Are you straighten up?")
.setSmallIcon(R.drawable.ic_notify)
.setAutoCancel(true)
.setContentIntent(notifClickPendingIntent)
.addAction(R.drawable.ic_posture_yes, "yes", yesPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL);
mNotificationManager.notify(NOTIFICATION_ID, builder.build());
}
}
CorrectPostureReceiver.java - 单击通知上的操作按钮时获取意图消息。
//
//imports
//
class CorrectPostureReceiver extends BroadcastReceiver {
private int mCount = 0;
private TextView mTxtCount;
private final String LOG_TAG = CorrectPostureReceiver.class.getSimpleName();
private MainActivity mainActivity;
public CorrectPostureReceiver(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
@Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "yes option clicked");
mTxtCount = mainActivity.findViewById(R.id.txt_count);
if (mTxtCount != null) {
mCount++;
mTxtCount.setText(Integer.toString(mCount));
}
}
public int getCount() {
return mCount;
}
public TextView getTxtCount() {
return mTxtCount;
}
}
AndroidManifest.xml 片段
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
如何解决这个问题? 如果您对我的代码有任何其他建议,请写信告诉我。
【问题讨论】:
-
请编辑您的问题并为
MainActivity添加清单内容。
标签: java android android-intent android-activity android-notifications