【问题标题】:Android Service needs to run always (Never pause or stop)Android 服务需要始终运行(从不暂停或停止)
【发布时间】:2018-10-27 17:06:47
【问题描述】:

我创建了一项服务,并希望始终运行该服务,直到我的手机重新启动或强制关闭。该服务应在后台运行。

创建服务和启动服务的示例代码:

启动服务:

Intent service = new Intent(getApplicationContext(), MyService.class);
getApplicationContext().startService(service);

服务:

public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO do something useful
        HFLAG = true;
        //smsHandler.sendEmptyMessageDelayed(DISPLAY_DATA, 1000);
        return Service.START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO for communication return IBinder implementation
        return null;
    }
}

清单声明:

<service
    android:name=".MyService"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
</service>

是否可以在应用程序暂停和其他任何情况下始终运行此服务。 一段时间后,我的应用程序暂停,服务也暂停或停止。 那么如何才能始终在后台运行此服务。

【问题讨论】:

  • 如果不使其成为系统映像的一部分,则不可能。在某些情况下,Android 可能会完全杀死您的应用程序。当您的应用程序被终止时,它的服务将无法运行。
  • 感谢您的回复,如何将我的应用程序作为系统映像的一部分。
  • 您需要修改固件。如果这是可以接受的,我可以写一个答案。
  • 你可以这样做......就像来电检查你的服务是否正在运行,如果没有,然后再次启动它......同样的方式使用媒体扫描仪,启动comlate,传入短信......等. 您必须检查每次服务是否运行,就像 Watsup 按摩服务一样。但我不建议你这样做。有关更多详细信息,请查看:stackoverflow.com/a/6091362/1168654stackoverflow.com/a/4353653/1168654

标签: java android service


【解决方案1】:

“是否可以在应用程序暂停或其他任何情况下始终运行此服务?”

是的。

  1. 在服务的 onStartCommand 方法中返回 START_STICKY。

    public int onStartCommand(Intent intent, int flags, int startId) {
            return START_STICKY;
    }
    
  2. 使用 startService(MyService) 在后台启动服务,这样无论绑定客户端的数量如何,它都始终保持活动状态。

    Intent intent = new Intent(this, PowerMeterService.class);
    startService(intent);
    
  3. 创建活页夹。

    public class MyBinder extends Binder {
            public MyService getService() {
                    return MyService.this;
            }
    }
    
  4. 定义服务连接。

    private ServiceConnection m_serviceConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                    m_service = ((MyService.MyBinder)service).getService();
            }
    
            public void onServiceDisconnected(ComponentName className) {
                    m_service = null;
            }
    };
    
  5. 使用 bindService 绑定到服务。

            Intent intent = new Intent(this, MyService.class);
            bindService(intent, m_serviceConnection, BIND_AUTO_CREATE);
    
  6. 对于您的服务,您可能希望收到通知,以便在其关闭后启动相应的活动。

    private void addNotification() {
            // create the notification
            Notification.Builder m_notificationBuilder = new Notification.Builder(this)
                    .setContentTitle(getText(R.string.service_name))
                    .setContentText(getResources().getText(R.string.service_status_monitor))
                    .setSmallIcon(R.drawable.notification_small_icon);
    
            // create the pending intent and add to the notification
            Intent intent = new Intent(this, MyService.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
            m_notificationBuilder.setContentIntent(pendingIntent);
    
            // send the notification
            m_notificationManager.notify(NOTIFICATION_ID, m_notificationBuilder.build());
    }
    
  7. 您需要修改清单以在单顶模式下启动活动。

              android:launchMode="singleTop"
    
  8. 请注意,如果系统需要资源并且您的服务不是很活跃,它可能会被终止。如果这是不可接受的,则使用 startForeground 将服务置于前台。

            startForeground(NOTIFICATION_ID, m_notificationBuilder.build());
    

【讨论】:

  • 一段时间后,此服务使用此功能自动进入睡眠状态。
  • 一个很好的答案 - 它运行良好。对类似问题的许多其他答案是部分的,而这个是完整的。
  • 你能详细说明#8吗?这是在哪里执行的?关于#5,这是否与启动服务的位置相同?我是否正确理解您使用通知来保持服务始终处于活动状态?
  • @Stephen Donecker 为什么我必须绑定它?
  • @SilviaHisham 你不知道。绑定通常在服务需要与活动通信时完成
【解决方案2】:

为了在自己的进程中启动服务,您必须在 xml 声明中指定以下内容。

<service
  android:name="WordService"
  android:process=":my_process" 
  android:icon="@drawable/icon"
  android:label="@string/service_name"
  >
</service> 

在这里你可以找到一个对我非常有用的好教程

http://www.vogella.com/articles/AndroidServices/article.html

希望对你有帮助

【讨论】:

  • android:name="WordService" 是否意味着 MyService
  • 是的,你有你自己的名字
  • @juan:你必须检查这个:developer.android.com/guide/topics/manifest/…
  • @DhavalSodhaParmar 这正是我的观点,我不明白你的意思
  • @Juan:这意味着您的服务在单独的线程中运行。这并不意味着你不能阻止它。
【解决方案3】:

如果你已经有一个服务并且希望它一直工作,你需要添加两件事:

  1. 在服务本身中:

    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }
    
  2. 在清单中:

    android:launchMode="singleTop"
    

除非服务中需要,否则无需添加绑定。

【讨论】:

  • 将 targetSdkVersion 设置为 30 时不起作用。 case1:将应用程序保持在后台超过 1 分钟:服务被终止。案例2:在应用程序被终止时:服务被终止
【解决方案4】:

一个简单的解决方案是在系统停止服务时重新启动服务。

我发现这个方法的这个非常简单的实现:

How to make android service unstoppable

【讨论】:

  • 这在不允许后台广播接收器启动服务的 Android O 中是如何工作的?
  • 将 targetSdkVersion 设置为 30 时不起作用。 case1:将应用程序保持在后台超过 3 分钟:服务被终止。案例2:在应用程序被终止时:服务被终止
【解决方案5】:

您可以为服务实现startForeground,即使它死了,您也可以在startCommand() 上使用START_STICKY 重新启动它。不确定这是不是正确的实现。

【讨论】:

  • 没有 START_STICKY 也可以正常工作,当 targetSdkVersion = 30 时。
【解决方案6】:

我找到了一种让Service 始终运行的简单明了的方法。

这家伙解释得这么清楚,并且使用了一个很好的算法。他的方法是在服务即将被杀死时发送一个广播,然后使用它来重新启动服务。

你应该看看:http://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android

【讨论】:

  • 这在不允许后台广播接收器启动服务的 Android O 中如何工作?
【解决方案7】:

您不需要广播接收器。如果有人愿意从 Stephen Donecker 的上述示例中复制其中一个 api(serviceconnection) 并将其粘贴到谷歌中,你会得到这个,https://www.concretepage.com/android/android-local-bound-service-example-with-binder-and-serviceconnection

【讨论】:

    【解决方案8】:

    将此添加到清单中。

          <service
            android:name=".YourServiceName"
            android:enabled="true"
            android:exported="false" />
    

    添加服务类。

    public class YourServiceName extends Service {
    
    
        @Override
        public void onCreate() {
            super.onCreate();
    
          // Timer task makes your service will repeat after every 20 Sec.
           TimerTask doAsynchronousTask = new TimerTask() {
                @Override
                public void run() {
                    handler.post(new Runnable() {
                        public void run() {
                           // Add your code here.
    
                         }
    
                   });
                }
            };
      //Starts after 20 sec and will repeat on every 20 sec of time interval.
            timer.schedule(doAsynchronousTask, 20000,20000);  // 20 sec timer 
                                  (enter your own time)
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO do something useful
    
          return START_STICKY;
        }
    
    }
    

    【讨论】:

      【解决方案9】:

      我已经解决了这个问题,我的示例代码如下。

      在你的 Main Activity 中添加下面一行,这里 BackGroundClass 是服务类。你可以在 New -> JavaClass 中创建这个类(在这个类中,添加你在其中的进程(任务)需要在后台发生)。为方便起见,先用通知铃声表示它们为后台进程。

       startService(new Intent(this, BackGroundClass .class));
      

      在 BackGroundClass 中,只需包含我的编码,您就可以看到结果。

      import android.app.Service;
      import android.content.Intent;
      import android.media.MediaPlayer;
      import android.os.IBinder;
      import android.provider.Settings;
      import android.support.annotation.Nullable;
      import android.widget.Toast;
      
      public class BackgroundService  extends Service {
          private MediaPlayer player;
          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
      @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
           player = MediaPlayer.create(this,Settings.System.DEFAULT_RINGTONE_URI);
              player.setLooping(true);
               player.start();
              return START_STICKY;
          }
       @Override
          public void onDestroy() {
              super.onDestroy();
               player.stop();
          }
      }
      

      并在 AndroidManifest.xml 中尝试添加此内容。

      <service android:name=".BackgroundService"/>
      

      运行程序,只需打开应用程序,您可能会在后台找到通知警报。甚至,您可能会退出应用程序,但您仍然可能会听到铃声警报,除非您关闭应用程序或卸载应用程序。这表示通知警报处于后台进程。像这样,您可以为背景添加一些进程。

      请注意:请不要使用 TOAST 进行验证,因为它只会运行一次,即使它处于后台进程。

      希望对您有所帮助...!!

      【讨论】:

      猜你喜欢
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多