即使应用程序关闭,也可以通过后台检查服务器中运行的服务显示安卓应用程序的通知(截击)



正如问题中所述,我希望后台进程从一个应用程序运行(每天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 的合适和推荐替代品

您可以在此处查看官方主题:工作经理

您有两个选项:

  1. 按照上述答案中的说明使用WorkManager,但如果您希望在非常准确的时间完成任务,则这些答案可能不好。在某些设备中,它们工作得很好,但在具有电池优化的自定义操作系统设备中,它并不像你期望的那样工作

  2. 如果你想在特定时间使用报警管理器+广播接收器+意向服务来完成一项任务,请记住,你必须将该服务作为前台服务启动。

感谢@Farid提供的解决方案。

帮助链接:

  1. 入门
  2. 工作经理周期
  3. 定期通知(enqueUniquePeriodicWork(

这只是最后一段代码:

  1. 在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"
    }
    
  2. 编写工作者(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());
    }
    

    }

  3. 在MainActivity.java的onCreate中调用Worker init

    NewPostNotification.scheduleReminder();
    

就是这样。

相关内容

最新更新