前台服务不会一直运行

5
在我的应用程序中,我使用了一个必须一直运行的前台服务。有时,前台服务会被停止。 在什么情况下,操作系统会杀死我的服务(即使有足够的内存,电池充满,手机正在充电)?
以下是我的代码示例:
public class ServiceTest extends Service {

    public static Thread serverThread = null;
    public Context context = this;

    public ServiceTest(Context context) {
        super();
        this.context = context;
    }

    public ServiceTest() {

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);

        if (this.serverThread == null) {
            this.serverThread = new Thread(new ThreadTest());
            this.serverThread.start();
        }

        return START_STICKY;
    }

    private class ThreadTest implements Runnable {

        @Override
        public void run() {
            Intent notificationIntent = new Intent(context, MainActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        Notification notification = new NotificationCompat.Builder(context)
                .setContentTitle("Notification title")
                .setContentText("Notification text")
                .setContentIntent(pendingIntent)
                .setAutoCancel(false)
                .setSmallIcon(R.drawable.android)
                .setOngoing(true).build();

                startForeground(101, notification);

                while(true){
                    //work to do
                }
        }


    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

你使用的是哪个版本的Android操作系统?是Oreo吗? - Vinayak B
到目前为止还没有Oreo版本。只有从Android 4-7版本。 - Madalina
我还通过一个广播接收器检查是否有BOOT_COMPLETED事件,如果有的话,就使用相同的方法从那里启动服务。 - Madalina
危险的实现编码和实现风格...虽然提供了答案... - sandhya sasane
谢谢您的回复。我还是Android编程的新手,感谢您指出问题所在。我会再次查看Android官方文档,并且这次我会更加仔细地阅读。 - Madalina
显示剩余2条评论
2个回答

6

你的代码中存在许多问题。它可能在语法上是正确的,所以"0个错误",但它在安卓方面是错误的。你的基础知识很差,阅读安卓文档和实现能力也很差。安卓不会运行非常糟糕的东西...

问题 1

你是否知道为了一个服务,你应该惯例性地重写 onCreate, onStartCommand, onBind, onDestroy 方法吗?

我没有看到 onDestroy....!!

问题 2

你知道如何通知吗?你的 onStartCommand 实现又毫无意义。

保持为空,只返回 START_STICKY

问题 3

你如何希望这在后台执行限制下运行?先在 oncreate 中进行通知,如果需要的话使用 startforeground ,告知安卓...

我没有看到它在那里... 你试图在 onstartcommand 中做到,而且它非常糟糕...

好吧,看一下下面的可运行代码:

public class RunnerService extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";

public RunnerService() { }

@Override
public void onCreate()
{
    super.onCreate();

    Log.d("RUNNER : ", "OnCreate... \n");

    Bitmap IconLg = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);

    mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
    mBuilder = new NotificationCompat.Builder(this, null);
    mBuilder.setContentTitle("My App")
            .setContentText("Always running...")
            .setTicker("Always running...")
            .setSmallIcon(R.drawable.ic_menu_slideshow)
            .setLargeIcon(IconLg)
            .setPriority(Notification.PRIORITY_HIGH)
            .setVibrate(new long[] {1000})
            .setVisibility(Notification.VISIBILITY_PUBLIC)
            .setOngoing(true)
            .setAutoCancel(false);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);

        // Configure the notification channel.
        notificationChannel.setDescription("Channel description");
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setVibrationPattern(new long[]{1000});
        notificationChannel.enableVibration(true);
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        mNotifyManager.createNotificationChannel(notificationChannel);

        mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
        startForeground(1, mBuilder.build());
    }
    else
    {
        mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
        mNotifyManager.notify(1, mBuilder.build());
    }
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    Log.d("RUNNER : ", "\nPERFORMING....");

    return START_STICKY;
}

@Override
public void onDestroy()
{
    Log.d("RUNNER : ", "\nDestroyed....");
    Log.d("RUNNER : ", "\nWill be created again automaticcaly....");
    super.onDestroy();
}


@Override
public IBinder onBind(Intent intent)
{
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("NOT_YET_IMPLEMENTED");
}
}

如何检查???

从最近使用列表中移除该应用程序,您应该在 logcat 日志中看到" Performing "消息...

在什么情况下会停止...?

它永远不会停止(直到下一次启动..!!)...是的,当用户强制停止应用程序时,它会停止。如果系统发现它的资源非常低,则很少会停止....这是一个非常罕见的情况,因为安卓已经有了很大的改进....

如何启动它....?????

无论它来自 mainactivity 还是来自 receiver 或任何 class

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            context.startForegroundService(new Intent(context, RunnerService.class));

        }
        else
        {
            context.startService(new Intent(context, RunnerService.class));

        }

如何检查服务是否已启动......?

别管它......即使你多次启动该服务......如果它已经运行......那么它不会再次启动......如果没有运行,那么就会启动它...!!


它运行得非常好。非常感谢您的回复。 - Madalina
如果一个服务需要用户数据(intent),那么在onCreate()中如何处理? - philoopher97

2
所选答案中的批评不合理,如果服务需要意图才能工作。
在较高版本的Android上,即使返回START_STICKY,系统也会在设备锁定时暂停任何前台服务,以最小化电力消耗。因此,为了使前台任务保持持续状态,需要使用唤醒锁。
这是Android文档描述的wakeLock:
为了避免耗尽电池,处于空闲状态的Android设备很快就会进入睡眠状态。但是,有时应用程序需要唤醒屏幕或CPU并保持其处于唤醒状态以完成某些工作。
要使前台服务持续运行,请在onCreate()中获取一个wakeLock。
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyApp::MyWakelockTag");
wakeLock.acquire();

如需更详细信息,请查看官方Android文档


这些信息真的帮助解决了前台服务在最新的安卓系统(如12和13)上经常出现延迟的问题。非常感谢! - Tieria

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接