正如问题中所述,我希望后台进程从一个应用程序运行(每天21:30(,该应用程序向服务器发出截击请求,并根据结果显示通知。点击通知后,会打开一个特定的链接(由应用程序处理(。
来自类的服务器请求和响应(通过async Volley(运行良好。链接处理程序也已设置。
我做了一项研究,对该课的使用感到困惑。看起来,我可以使用:
- 服务OR
- BroadcastReceiver(带AlarmManager(
使用AlarmManager(在清单中添加receiver
标记(,我设置了在MainActivity.java的onCreate中调用的以下方法:
private void setAlarms()
{
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this, NewNewsNotification.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, i, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 60, alarmIntent);
if (alarmMgr!= null) {
alarmMgr.cancel(alarmIntent);
}
}
NewNewsNotification.java
@Override
public void onReceive(Context context, Intent intent) {
rCtx= context;
fetch_last_update();
}
public void fetch_last_update()
{
VolleyCallback();
VolleyService = new AsyncJsonFetch(ResultCallback, rCtx);
try {
JSONObject sendObj = new JSONObject();
mVolleyService.postDataVolley("POSTCALL", "news", sendObj);
} catch (JSONException e) {
e.printStackTrace();
}
}
public void VolleyCallback()
{
pResultCallback = new AsyncJsonData() {
@Override
public void notifySuccess(String requestType, JSONObject response) throws JSONException {
int stat = (int) response.get("status");
if (stat == 1) {
JSONObject msgJSON = (JSONObject) response.get("msg");
Log.d(TAG, "msgJSON: "+msgJSON);
/*The above log is working correctly. PROCESS THE JSON HERE AND GENERATE THE NOTIFICATION*/
}
}
@Override
public void notifyError(String requestType, VolleyError error) {
Log.d(TAG, "Volley requester " + requestType);
Log.d(TAG, "Volley JSON post" + "That didn't work!");
}
};
}
正确的方法是什么?如何实施?如何启动可点击的通知?
Android有更新更好的解决方案,完全适合您的需求
WorkManager API是所有以前的Android后台调度API 的合适和推荐替代品
您可以在此处查看官方主题:工作经理
您有两个选项:
-
按照上述答案中的说明使用WorkManager,但如果您希望在非常准确的时间完成任务,则这些答案可能不好。在某些设备中,它们工作得很好,但在具有电池优化的自定义操作系统设备中,它并不像你期望的那样工作
-
如果你想在特定时间使用报警管理器+广播接收器+意向服务来完成一项任务,请记住,你必须将该服务作为前台服务启动。
感谢@Farid提供的解决方案。
帮助链接:
- 入门
- 工作经理周期
- 定期通知(enqueUniquePeriodicWork(
这只是最后一段代码:
-
在build.gradle(app(中添加依赖项:
dependencies { ... def work_version = "2.4.0" implementation "androidx.work:work-runtime:$work_version" implementation "androidx.work:work-rxjava2:$work_version" androidTestImplementation "androidx.work:work-testing:$work_version" }
-
编写工作者(NewNewsNotification.java(
public class NewNewsNotification extends Worker { private static final String TAG="NewNewsNotification"; private static Context rCtx; private RequestQueue reQueue; private String NEWS_TYPE= "post"; private static final int EXEC_MIN= 15; AsyncJsonFetch mVolleyService; AsyncJsonData pResultCallback = null; //Context rCtx; public NewNewsNotification( @NonNull Context context, @NonNull WorkerParameters params) { super(context, params); rCtx= context; } public static void scheduleReminder() { Log.d(TAG, "queueing req"); //WorkRequest notificationWork = new PeriodicWorkRequest.Builder(NewNewsNotification.class, 24, TimeUnit.HOURS).build(); Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresStorageNotLow(true) .build(); PeriodicWorkRequest notificationWork = new PeriodicWorkRequest.Builder(NewNewsNotification.class, EXEC_MIN, TimeUnit.MINUTES).addTag(TAG).setConstraints(constraints).build(); WorkManager instance = WorkManager.getInstance(rCtx); instance.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, notificationWork); } @NonNull @Override public Result doWork() { try { Log.d(TAG, "fetch_last_update called"); fetch_last_update(); return Result.success(); }catch (Throwable e) { e.printStackTrace(); Log.e(TAG, "Error fetching data", e); return Result.failure(); } } public void fetch_last_update() { postDetVolleyCallback(); mVolleyService = new AsyncJsonFetch(pResultCallback, rCtx); try { JSONObject sendObj = new JSONObject(); sendObj.put("lastdate", 1); sendObj.put("NEWS_TYPE", NEWS_TYPE); mVolleyService.newsDataVolley("POSTCALL", "news", sendObj); } catch (JSONException e) { e.printStackTrace(); } } public void postDetVolleyCallback() { pResultCallback = new AsyncJsonData() { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void notifySuccess(String requestType, JSONObject response) throws JSONException { int stat = (int) response.get("status"); if (stat == 1) { /***********************************************************/ JSONObject msgJSON = (JSONObject) response.get("msg"); int ldate= Integer.parseInt(msgJSON.get("date").toString()); JSONArray tparray= (JSONArray) msgJSON.get("news"); JSONObject tnews= (JSONObject) tparray.get(0); String title= tnews.get("news_title").toString(); String excerpt= tnews.get("news_excerpt").toString(); int id= Integer.parseInt(tnews.get("ID").toString()); sendNotification(title, excerpt, id); } } @Override public void notifyError(String requestType, VolleyError error) { Log.d(TAG, "Volley requester " + requestType); Log.d(TAG, "Volley JSON post" + "That didn't work!"); } }; } @RequiresApi(api = Build.VERSION_CODES.KITKAT) private void sendNotification(String title, String text, int id) { String cl_url= rCtx.getString(R.string.client_link); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(cl_url+"?p="+id)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); NotificationManager notificationManager = (NotificationManager)getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("default", "Default", NotificationManager.IMPORTANCE_DEFAULT); Objects.requireNonNull(notificationManager).createNotificationChannel(channel); } NotificationCompat.Builder notification = new NotificationCompat.Builder(getApplicationContext(), "default") .setContentTitle(title) .setContentText(text) .setContentIntent(pendingIntent) .setSmallIcon(R.mipmap.ic_launcher) .setAutoCancel(true); Objects.requireNonNull(notificationManager).notify(id, notification.build()); }
}
-
在MainActivity.java的onCreate中调用Worker init
NewPostNotification.scheduleReminder();
就是这样。