【问题标题】:Android: Check if service is running via. bindServiceAndroid:检查服务是否正在运行。绑定服务
【发布时间】:2011-05-25 11:12:54
【问题描述】:

检查 Android 服务是否正在运行的最佳方法是什么?我知道ActivityManager API,但似乎不建议在类似于我的场景(source)中使用 API。我也知道使用全局/持久变量来维护服务状态的可能性。

我尝试使用 bindService 并将标志设置为 0,但我遇到了与 source 链接上的人相同的问题(唯一的例外是,我正在尝试 @ 987654325@ 与本地服务)。

下面的调用

getApplicationContext().bindService(new Intent(getApplicationContext(),
        MyService.class), mServiceConnection, 0);

始终返回 true,但不会连接。这是预期的行为吗?在我看来 bindService 应该返回 false 如果服务尚未运行(它不是,我已经检查过)或者如果 BIND_AUTO_CREATE 标志未设置(同样,它不是)。

【问题讨论】:

    标签: android service state


    【解决方案1】:

    我也有同样的问题;似乎最著名的解决方案是在 WhatService 中创建一个公共静态布尔值,在 onCreate(或 onStartCommand,您的选择)期间设置为 true,在 onDestroy 期间设置为 false。然后,您可以从同一个 apk 中的任何其他类访问它。不过,这可能很激烈。 Android 中没有 API 可以检查服务是否正在运行(没有副作用):请参阅 http://groups.google.com/group/android-developers/browse_thread/thread/8c4bd731681b8331/bf3ae8ef79cad75d

    我认为竞争条件来自操作系统可能随时终止远程服务(在另一个进程中)的事实。如上所述,检查本地服务(相同的进程)对我来说似乎没有竞争——如果操作系统终止服务,它也会终止检查其状态的任何内容。

    【讨论】:

      【解决方案2】:

      使用共享首选项保存服务运行标志。

      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
          int res = super.onStartCommand(intent, flags, startId);
          setRunning(true);
          return res;
      }
      
      @Override
      public void onDestroy() {
          super.onDestroy();
          setRunning(false);
      }
      
      private void setRunning(boolean running) {
          SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
          SharedPreferences.Editor editor = pref.edit();
      
          editor.putBoolean(PREF_IS_RUNNING, running);
          editor.apply();
      }
      
      public static boolean isRunning(Context ctx) {
          SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx.getApplicationContext());
          return pref.getBoolean(PREF_IS_RUNNING, false);
      }
      

      【讨论】:

      • 这不是一个好主意,SharedPreferences 被持久化到非易失性存储中,所以如果由于某种原因设备崩溃或断电,那么您的onDestroy 将不会被调用,并且下次您启动您的应用程序会认为服务正在运行,即使它没有运行。
      • 是的,我同意。 SharedPreferences 不适用于它。但是,可以在应用启动时删除服务运行首选项。另一种方式:将运行 bool var 的服务存储在 Application 对象中。
      • onDestroy 并不总是调用
      • 最好保留一个静态布尔值而不是它,因为如果用户终止应用程序(例如:清除最近的应用程序)或设备意外关闭(例如:电池电量不足),共享首选项仍将是是的。
      【解决方案3】:

      另一种方法:

      public static boolean isServiceRunning(Context ctx, String serviceClassName) {
          ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
          for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
              if (TrackingService.class.getName().equals(serviceClassName)) {
                  return true;
              }
          }
          return false;
      }
      

      【讨论】:

      • 当我使用上面的代码时,它只给我系统运行服务的信息。我正在寻找所有服务,包括我创建的服务
      【解决方案4】:

      我也有同样的需求,发现运行 .bindService 时已经绑定了其他东西,这会导致错误。我在运行 .bindService 之前就这样做了

      try{
          context.unbindService(fetch_connection);
      } catch (IllegalArgumentException e){
          System.out.println("Unbinding didn't work. little surprise");
      }
      

      【讨论】:

      • 这只是检查您是否绑定到该服务。不管它是否开始。
      【解决方案5】:

      【讨论】:

        【解决方案6】:

        在您的活动中,您可以使用您的服务实例简单地检查它 就我而言,我使用

          button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
        
                    Intent intent=new Intent(MainActivity.this, MyService.class);
                    //startService(intent);
                    bindService(intent,serviceConnection,BIND_AUTO_CREATE);
                    if (myService!=null)
                    {
                        myService.RecData(editText.getText().toString());
                    }
                }
            });
        }
        
        ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Toast.makeText(MainActivity.this,"onServiceConnected called",Toast.LENGTH_SHORT).show();
                MyService.MyBinder myBinder= (MyService.MyBinder) iBinder;
                myService= myBinder.getServiceInstant();
                myService.SetActivity(MainActivity.this);
                myService.RecData(editText.getText().toString());
            }
        

        【讨论】:

          【解决方案7】:

          如果服务正在运行/未运行,您打算做什么?为什么不直接打电话给startService()。如果它没有运行,它将创建它,如果它运行,它将调用它的 onStart() 方法。

          【讨论】:

          • 假设我想打印一条消息“服务正在运行”或“服务未运行”。这就是为什么我必须获取服务是否正在运行的信息。我不能通过调用 startService 来做到这一点。
          • 但是你为什么要打印这条消息呢?如果服务未运行,您只能做两件事。要么开始,要么不开始。
          • 因为我想通知用户服务是否正在运行。用户应手动启动和停止服务(通过按下按钮)。当用户关闭活动(返回按钮)时,服务应该保持运行。并且 Activity 应该知道,当用户下次启动它时,该服务已经在运行。
          • 我认为让用户了解服务通常是个坏主意。相反,让用户了解功能。如果由于未连接到服务而无法完成功能,请优雅地失败并通知用户。如果您在用户每次运行您的应用程序时都告诉他们服务正在运行,那会非常烦人。他们不在乎服务是否正在运行,他们想要的只是功能。
          • 好的,我知道我在这里没有提供足够的信息 - 我说活动将打印一条消息,只是为了说明在特定时间需要什么类型的信息(服务是否正在运行)(在活动开始时)。我并不是真的要关注可用性方面,因为其他应用程序正在使用类似的模式(例如 android 音乐播放器),而是关注如何做到这一点。那么,让我重新提出我的问题 - android 音乐播放器如何知道,何时在活动开始时显示“播放按钮”(音乐播放器停止)以及何时显示“暂停按钮”(mp 正在运行)?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-09
          • 1970-01-01
          • 2013-04-04
          • 2021-08-15
          • 2015-06-26
          • 2011-07-12
          • 1970-01-01
          相关资源
          最近更新 更多