通知在不遵循 AlarmManager 的情况下工作
Notifications works without following the AlarmManager
我创建了两个不同的每日通知。两者都会 运行 在不同的给定时间。第二个通知将从 API 获取一些数据,检查来自 API 的数据是否与今天的日期匹配,并显示它。
第一次通知 运行 每次我打开闹钟(我已经创建了打开或关闭通知的设置),但有时不会 运行给出。
另一个甚至不会 运行 BroadcastReceiver class 即使我已经设置了闹钟。
这是我的代码
MainActivity.java
public static void setAlarmDaily(Context context){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND,0);
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(EXTRA_TYPE, DAILY_REQUEST_CODE);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,100,intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(alarmManager != null){
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent);
}
}
public static void setAlarmRelease(Context context){
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(EXTRA_TYPE, LATEST_REQUEST_CODE);
AlarmManager alarmManager1 = (AlarmManager)context.getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context,101,intent,PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.HOUR_OF_DAY, 8);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND,0);
if(alarmManager1 != null){
alarmManager1.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent1);
}
}
NotifyService.java
@Override
public void onReceive(final Context context, Intent intent) {
int type = intent.getIntExtra(EXTRA_TYPE, 101);
if(type==100){
showNotificationDaily(context);
}else {
final PendingResult pendingResult = goAsync();
Thread thread = new Thread(){
public void run(){
AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
ArrayList<Movie> listMov = null;
String result = new String(responseBody);
JSONObject responseObject = new JSONObject(result);
JSONArray results = responseObject.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
int id = results.getJSONObject(i).getInt("id");
String title = results.getJSONObject(i).getString("title");
String releaseDate = results.getJSONObject(i).getString("release_date");
Movie mov = new Movie();
mov.setId(id);
mov.setTitle(title);
mov.setReleaseDate(releaseDate);
listMov.add(mov);
}
listMovie = listMov;
pendingResult.finish();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
}
});
}
};
thread.start();
ArrayList<Movie> movies = listMovie;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date date = new Date();
String now = dateFormat.format(date);
for(Movie movieItem : movies){
if(movieItem.getReleaseDate().equals(now)){
showNotificationRelease(context, movieItem.getId(), movieItem.getTitle());
Log.d(TAG,movieItem.getReleaseDate());
}
}
}
}
public void showNotificationRelease(Context context, int id, String title){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager2 = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, DetailActivity.class);
Movie movie = new Movie();
movie.setId(id);
movie.setTitle(title);
movie.setType("movie");
i.putExtra(DetailActivity.EXTRA_DETAIL,movie);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent2 = PendingIntent.getActivity(context, 101, i, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notification2 = new Notification.Builder(context)
.setContentIntent(pIntent2)
.setContentTitle(context.getString(R.string.release_now_string))
.setContentText(title + context.getString(R.string.has_release_string))
.setSmallIcon(R.drawable.ic_live_tv_black_24dp)
.setSound(sound)
.setAutoCancel(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel dailyNotificationChannel = new NotificationChannel("101",
"Latest",
NotificationManager.IMPORTANCE_DEFAULT);
dailyNotificationChannel.enableVibration(true);
dailyNotificationChannel.setVibrationPattern(new long[]{1000, 1000, 1000, 1000, 1000});
notification2.setChannelId("100");
if(notificationManager2 != null){
notificationManager2.createNotificationChannel(dailyNotificationChannel);
}
}
if(notificationManager2 != null){
notificationManager2.notify(101, notification2.build());
}
}
public void showNotificationDaily(Context context){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent = PendingIntent.getActivity(context, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notification = new Notification.Builder(context)
.setContentIntent(pIntent)
.setContentTitle(context.getString(R.string.good_morning_string))
.setContentText(context.getString(R.string.check_app_string))
.setSmallIcon(R.drawable.ic_movie_black_24dp)
.setSound(sound)
.setAutoCancel(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel dailyNotificationChannel = new NotificationChannel("100",
"Daily",
NotificationManager.IMPORTANCE_DEFAULT);
dailyNotificationChannel.enableVibration(true);
dailyNotificationChannel.setVibrationPattern(new long[]{1000, 1000, 1000, 1000, 1000});
notification.setChannelId("100");
if(notificationManager != null){
notificationManager.createNotificationChannel(dailyNotificationChannel);
}
}
if(notificationManager != null){
notificationManager.notify(100, notification.build());
}
}
清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.moviecatalogue">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission
android:name="com.dicoding.mynotesapp.READ_DATABASE"
android:protectionLevel="normal" />
<permission
android:name="com.dicoding.mynotesapp.WRITE_DATABASE"
android:protectionLevel="normal" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".widget.ImageBannerWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/image_banner_widget_info" />
</receiver>
<activity android:name=".activity.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.MainActivity" />
</activity>
<activity android:name=".activity.DetailActivity" />
<activity
android:name=".activity.MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
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=".service.NotifyService" />
<service
android:name="com.example.moviecatalogue.widget.StackWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<provider
android:name=".provider.FavoriteProvider"
android:authorities="com.example.moviecatalogue"
android:exported="true"
android:readPermission="com.example.moviecatalogue.READ_DATABASE"
android:writePermission="com.example.moviecatalogue.WRITE_DATABASE" />
</application>
我不知道我的代码有什么问题。我真的需要这方面的帮助。
尝试更改
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent);
到
long dateTime = calendar.getTimeInMillis();
if (dateTime <= System.currentTimeMillis()) {
time = dateTime + 24 * 3600 * 1000;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, dateTime ,
AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, dateTime ,
AlarmManager.INTERVAL_DAY, pendingIntent);
}
如果您阅读 Android 与 AlarmManager
相关的文档
Beginning with API 19 (Build.VERSION_CODES.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,
android.app.PendingIntent) and setExact(int, long,
android.app.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.
编辑:
我建议在各自的任务完成后,在您的 broadcastReceiver 中调用您的 setAlarmDaily
和 setAlarmRelease
方法。并更改一次警报的方法。像这样:
long dateTime = calendar.getTimeInMillis();
if (dateTime <= System.currentTimeMillis()) {
time = dateTime + 24 * 3600 * 1000;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//alarmManager.setExact(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent); // not suggested
// 15 mins of window to call the alarm and have battery optimization
long windowMillis = 15 * 60 * 1000L;
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, dateTime ,
windowMillis, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent);
}
我创建了两个不同的每日通知。两者都会 运行 在不同的给定时间。第二个通知将从 API 获取一些数据,检查来自 API 的数据是否与今天的日期匹配,并显示它。
第一次通知 运行 每次我打开闹钟(我已经创建了打开或关闭通知的设置),但有时不会 运行给出。
另一个甚至不会 运行 BroadcastReceiver class 即使我已经设置了闹钟。
这是我的代码
MainActivity.java
public static void setAlarmDaily(Context context){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND,0);
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(EXTRA_TYPE, DAILY_REQUEST_CODE);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,100,intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(alarmManager != null){
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent);
}
}
public static void setAlarmRelease(Context context){
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(EXTRA_TYPE, LATEST_REQUEST_CODE);
AlarmManager alarmManager1 = (AlarmManager)context.getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context,101,intent,PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.HOUR_OF_DAY, 8);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND,0);
if(alarmManager1 != null){
alarmManager1.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent1);
}
}
NotifyService.java
@Override
public void onReceive(final Context context, Intent intent) {
int type = intent.getIntExtra(EXTRA_TYPE, 101);
if(type==100){
showNotificationDaily(context);
}else {
final PendingResult pendingResult = goAsync();
Thread thread = new Thread(){
public void run(){
AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
ArrayList<Movie> listMov = null;
String result = new String(responseBody);
JSONObject responseObject = new JSONObject(result);
JSONArray results = responseObject.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
int id = results.getJSONObject(i).getInt("id");
String title = results.getJSONObject(i).getString("title");
String releaseDate = results.getJSONObject(i).getString("release_date");
Movie mov = new Movie();
mov.setId(id);
mov.setTitle(title);
mov.setReleaseDate(releaseDate);
listMov.add(mov);
}
listMovie = listMov;
pendingResult.finish();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
}
});
}
};
thread.start();
ArrayList<Movie> movies = listMovie;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date date = new Date();
String now = dateFormat.format(date);
for(Movie movieItem : movies){
if(movieItem.getReleaseDate().equals(now)){
showNotificationRelease(context, movieItem.getId(), movieItem.getTitle());
Log.d(TAG,movieItem.getReleaseDate());
}
}
}
}
public void showNotificationRelease(Context context, int id, String title){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager2 = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, DetailActivity.class);
Movie movie = new Movie();
movie.setId(id);
movie.setTitle(title);
movie.setType("movie");
i.putExtra(DetailActivity.EXTRA_DETAIL,movie);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent2 = PendingIntent.getActivity(context, 101, i, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notification2 = new Notification.Builder(context)
.setContentIntent(pIntent2)
.setContentTitle(context.getString(R.string.release_now_string))
.setContentText(title + context.getString(R.string.has_release_string))
.setSmallIcon(R.drawable.ic_live_tv_black_24dp)
.setSound(sound)
.setAutoCancel(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel dailyNotificationChannel = new NotificationChannel("101",
"Latest",
NotificationManager.IMPORTANCE_DEFAULT);
dailyNotificationChannel.enableVibration(true);
dailyNotificationChannel.setVibrationPattern(new long[]{1000, 1000, 1000, 1000, 1000});
notification2.setChannelId("100");
if(notificationManager2 != null){
notificationManager2.createNotificationChannel(dailyNotificationChannel);
}
}
if(notificationManager2 != null){
notificationManager2.notify(101, notification2.build());
}
}
public void showNotificationDaily(Context context){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent = PendingIntent.getActivity(context, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notification = new Notification.Builder(context)
.setContentIntent(pIntent)
.setContentTitle(context.getString(R.string.good_morning_string))
.setContentText(context.getString(R.string.check_app_string))
.setSmallIcon(R.drawable.ic_movie_black_24dp)
.setSound(sound)
.setAutoCancel(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel dailyNotificationChannel = new NotificationChannel("100",
"Daily",
NotificationManager.IMPORTANCE_DEFAULT);
dailyNotificationChannel.enableVibration(true);
dailyNotificationChannel.setVibrationPattern(new long[]{1000, 1000, 1000, 1000, 1000});
notification.setChannelId("100");
if(notificationManager != null){
notificationManager.createNotificationChannel(dailyNotificationChannel);
}
}
if(notificationManager != null){
notificationManager.notify(100, notification.build());
}
}
清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.moviecatalogue">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission
android:name="com.dicoding.mynotesapp.READ_DATABASE"
android:protectionLevel="normal" />
<permission
android:name="com.dicoding.mynotesapp.WRITE_DATABASE"
android:protectionLevel="normal" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".widget.ImageBannerWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/image_banner_widget_info" />
</receiver>
<activity android:name=".activity.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.MainActivity" />
</activity>
<activity android:name=".activity.DetailActivity" />
<activity
android:name=".activity.MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
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=".service.NotifyService" />
<service
android:name="com.example.moviecatalogue.widget.StackWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<provider
android:name=".provider.FavoriteProvider"
android:authorities="com.example.moviecatalogue"
android:exported="true"
android:readPermission="com.example.moviecatalogue.READ_DATABASE"
android:writePermission="com.example.moviecatalogue.WRITE_DATABASE" />
</application>
我不知道我的代码有什么问题。我真的需要这方面的帮助。
尝试更改
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,pendingIntent);
到
long dateTime = calendar.getTimeInMillis();
if (dateTime <= System.currentTimeMillis()) {
time = dateTime + 24 * 3600 * 1000;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, dateTime ,
AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, dateTime ,
AlarmManager.INTERVAL_DAY, pendingIntent);
}
如果您阅读 Android 与 AlarmManager
相关的文档Beginning with API 19 (Build.VERSION_CODES.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, android.app.PendingIntent) and setExact(int, long, android.app.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.
编辑:
我建议在各自的任务完成后,在您的 broadcastReceiver 中调用您的 setAlarmDaily
和 setAlarmRelease
方法。并更改一次警报的方法。像这样:
long dateTime = calendar.getTimeInMillis();
if (dateTime <= System.currentTimeMillis()) {
time = dateTime + 24 * 3600 * 1000;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//alarmManager.setExact(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent); // not suggested
// 15 mins of window to call the alarm and have battery optimization
long windowMillis = 15 * 60 * 1000L;
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, dateTime ,
windowMillis, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent);
}