首页 > 解决方案 > 关闭应用程序时服务不执行,但在后台执行时会执行

问题描述

我一直在尝试制作警报应用程序。我一直在努力制作全屏通知。我终于设法做到了,但它仅在应用程序在后台运行时才有效。

当您关闭应用程序时,它也需要工作。我不明白我应该做些什么来实现这一目标。我知道这是可能的,因为我每天使用的闹钟应用程序能够做到这一点。

Mainactivity.java

package com.example.wekkerapp;
import java.util.Calendar;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final String CHANNEL_ID = "my_channel";
    static final String FULL_SCREEN_ACTION = "full_screen_action";
    static final int NOTIFICATION_ID = 1;

    private void createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "Alarm";
            String description = "Het alarm gaat";
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel("2", name, importance);
            channel.setDescription(description);
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            NotificationManager notificationManager = (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        createNotificationChannel(this);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TimePicker klok = findViewById(R.id.timePicker1);
        klok.setIs24HourView(true);
        final Button getTimeBtn = findViewById(R.id.getTimeBtn);
        final TextView showText = findViewById(R.id.showText);

        final AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);


        getTimeBtn.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FULL_SCREEN_ACTION, null, getApplicationContext(), WekkerService.class);
                PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                int uur = klok.getHour();
                int minuut = klok.getMinute();
                Calendar cal = Calendar.getInstance();
                cal.set(Calendar.HOUR_OF_DAY, uur);
                cal.set(Calendar.MINUTE, minuut);
                cal.set(Calendar.SECOND, 0);
                cal.set(Calendar.MILLISECOND, 0);
                Toast.makeText(getApplication().getApplicationContext(), "Alarm gaat om " + uur + ":" + minuut,Toast.LENGTH_LONG).show();
                alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);


                showText.setText(Integer.toString(uur) + ':' + Integer.toString(minuut));
                NotificationManagerCompat.from(getApplicationContext()).cancel(NOTIFICATION_ID);

            }
        });


    }

    static void CreateFullScreenNotification(Context context) {
        Intent intent = new Intent(context, MainActivity2.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(context, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_launcher_background)
                        .setContentTitle("Alarm")
                        .setContentText("Het alarm gaat")
                        .setPriority(NotificationCompat.PRIORITY_MAX)
                        .setCategory(NotificationCompat.CATEGORY_ALARM)
                        .setContentIntent(pendingIntent)
                        .setFullScreenIntent(pendingIntent, true);
        NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notificationBuilder.build());
    }

    private static void createNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

            if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);
                channel.setDescription("channel_description");
                notificationManager.createNotificationChannel(channel);
            }
        }
    }
}

Wekkerservice.java

package com.example.wekkerapp;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.util.Log;

import androidx.annotation.Nullable;

public class WekkerService extends IntentService {

    public static MediaPlayer mediaPlayer;
    public WekkerService() {
        super("WekkerService");

    }

    @Override
    public void onCreate() {
        super.onCreate(); // if you override onCreate(), make sure to call super().
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.d("test", "onHandleIntent: ");
        mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.alarmpie);
        if (MainActivity.FULL_SCREEN_ACTION.equals(intent.getAction()))

            mediaPlayer.setLooping(true);
        mediaPlayer.start(); // no need to call prepare(); create() does that for you
        MainActivity.CreateFullScreenNotification(getApplicationContext());

    }
}

Mainactivity2.java

package com.example.wekkerapp;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.NotificationCompat;

import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class MainActivity2 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Button stopbutton = findViewById(R.id.button2);
        stopbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                WekkerService.mediaPlayer.stop();
            }
        });

    }
}

标签: javaandroidservicebackground-process

解决方案


我建议您使用 BroadcastReceiver,然后从其 onReceive 方法启动服务。因此,在您的 MainActivity 的 onClick 侦听器中,您应该更改以下待处理的意图,如下所示:

PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

并且您传入的意图应该启动一个广播接收器。警报管理器启动 BroadcastReceiver 后,您应该立即从其 onReceive 方法启动服务。

请记住,由于最近的更改,操作系统不会让您随时随地启动服务或后台服务!

如果应用程序已关闭并且您想启动服务,则应该将其作为 ForgroundService 启动并显示通知(您有 5 秒的时间进行此调用),否则它将抛出 RemoteServiceException,这就是您服务中的代码不会运行的原因.

我强烈建议您看看这个答案: https ://stackoverflow.com/a/56471104/9023032 这也是另一个有用的答案,可能会变得很方便: https ://stackoverflow.com/a/54035247/9023032


推荐阅读