【问题标题】:How to call methods of a Service from activity?如何从活动中调用服务的方法?
【发布时间】:2011-06-18 05:05:51
【问题描述】:

我只是想从我的活动中调用本地服务的方法。我该怎么做?

【问题讨论】:

    标签: android service android-activity


    【解决方案1】:

    这是一个可能有帮助的示例
    Server.java:

    package com.example.bindservice.binder;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    
    public class Server extends Service {
    
        IBinder mBinder = new LocalBinder();
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        public class LocalBinder extends Binder {
            public Server getServerInstance() {
                return Server.this;
            }
        }
    
        public String getTime() {
            SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return mDateFormat.format(new Date());
        }
    }
    

    Client.java

    package com.example.bindservice.binder;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.example.bindservice.binder.Server.LocalBinder;
    
    public class Client extends Activity {
    
        boolean mBounded;
        Server mServer;
        TextView text;
        Button button;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            text = (TextView)findViewById(R.id.text);
            button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    text.setText(mServer.getTime());
                }
            });
        }
    
        @Override
        protected void onStart() {
            super.onStart();
    
            Intent mIntent = new Intent(this, Server.class);
            bindService(mIntent, mConnection, BIND_AUTO_CREATE);
        };
    
        ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Toast.makeText(Client.this, "Service is disconnected", 1000).show();
                mBounded = false;
                mServer = null;
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Toast.makeText(Client.this, "Service is connected", 1000).show();
                mBounded = true;
                LocalBinder mLocalBinder = (LocalBinder)service;
                mServer = mLocalBinder.getServerInstance();
            }
        };
    
        @Override
        protected void onStop() {
            super.onStop();
            if(mBounded) {
                unbindService(mConnection);
                mBounded = false;
            }
        };
    }
    

    【讨论】:

    • 如果服务被强制停止,我会接到 onServiceDisconnected 的电话吗?
    • 为什么调用一个简单的函数这么难
    • @Mr.Z 也许你没有将服务绑定到Android中的活动stackoverflow.com/questions/1916253/…
    • 这应该是正确的答案。谢谢。你节省了我的时间。
    【解决方案2】:

    在“本地服务示例”下的服务文档中有此权限的示例代码:

    http://developer.android.com/reference/android/app/Service.html#LocalServiceSample

    同样对于那些建议使用aidl 的人——如果您的服务和客户端都是您自己的.apk 的一部分并且在同一个进程中运行(默认行为),则不需要aidl;它只是额外的复杂性,并没有给你任何东西。

    【讨论】:

      【解决方案3】:

      如何调用普通的 Java 方法?

      A obj = new A();
      obj.method();
      

      Service 是一个 Java 类。那么如何调用服务方法呢?

      serviceObj.method();
      

      现在真正的问题是如何创建服务对象?

      Service serviceObj = new Service();

      绝对不是。

      在 Android 中,Service 是由 Android 操作系统创建、销毁和管理的系统组件。
      要创建服务对象,您需要 IBinder

      这是您从IBinder 获取服务对象的方法。

      一旦你拥有了 serviceObject.它将像任何普通的 Java 对象一样工作。
      上面图中解释的东西叫做Binding a Service

      绑定使得从 Activity 观察后台服务成为可能。通过绑定,我们可以通过两种方式进行通信,即ActivityService
      Prateek Yadav 已经提供了出色的代码 sn-p。你可以使用它。

      注意事项

      • 永远不要忘记取消绑定服务,否则会导致 ResourceLeak。
      • 您可以按任意顺序拨打startService(intent)bindService(mIntent, mConnection, BIND_AUTO_CREATE)。绑定和启动服务是两个独立的东西。

      【讨论】:

        【解决方案4】:

        实现此目的的一种方法是使用Android's AIDL 定义一个接口,并利用Binder 子系统执行IPC。我发布的链接中有一组很棒的说明。如果您有问题,我会从那里开始,然后在这里发布。尽管是一个相当复杂的主题 (IPC) Android 和 Binder 在使它变得非常简单方面做得非常好(至少在开始时,我相信如果你愿意,你可以让它变得复杂;-))

        编辑 正如 cmets 中所指出的,如果 Service 和客户端在同一进程中运行,则这是不必要的。除非您另外指定,否则这是默认设置。但是,无论如何它仍然有效,只是增加了一点复杂性。

        【讨论】:

        • AIDL 仅在服务和活动位于不同应用程序中时才需要。如果您的服务和活动对您的应用程序来说是本地的(这是常见的情况),请参阅@hackbod 的回复
        • @odedfos 你说对了一部分。使用 AIDL 的必要性取决于调用者和被调用者是否在不同的进程中,不一定是不同的应用程序。大多数情况下,应用程序只有一个进程,因此这不是问题,但您可以指定服务在与 UI 不同的进程中运行,即使在同一个应用程序中也是如此。
        • 本地服务定义不使用IPC,问题是关于本地服务,所以这个答案是错误的。
        • @Ixx 默认情况下不会,但您可以指定它们在单独的进程中运行。此外,如果您在与客户端相同的进程中运行服务,这确实工作 ergo 它并没有错,它只是更复杂并且需要更多的开销。
        【解决方案5】:

        我不知道你的问题出在哪里,请发布一些代码。 使用 Binder,Activity 可以访问服务对象。请参阅 API 中的示例以创建活动和服务之间的连接。

        在您的活动中拥有服务对象,您可以简单地调用:
        mService.yourMethod();
        如果您能准确描述您的问题,我们可以为您提供更好的帮助,正如我所说,发布一些 sn-ps。

        【讨论】:

        【解决方案6】:

        Kotlin 的等效代码

        MainActivity.kt

        private var mBounded = false
        
        private var foregroundService: ForegroundService? = null
        
         override fun onPostCreate(savedInstanceState: Bundle?) {
            super.onPostCreate(savedInstanceState)
        
            btn_start_service.setOnClickListener { startMyService(); }
        
            btn_stop_service.setOnClickListener { stopMyService(); }
        
            mConnection = object : ServiceConnection {
                override fun onServiceDisconnected(name: ComponentName) {
                    Toast.makeText(this@MainActivity, "Service is disconnected", Toast.LENGTH_SHORT)
                        .show()
                    mBounded = false
                    foregroundService = null
                }
        
                override fun onServiceConnected(name: ComponentName, service: IBinder) {
                    Toast.makeText(this@MainActivity, "Service is connected", Toast.LENGTH_SHORT).show()
                    mBounded = true
                    val mLocalBinder = service as LocalBinder
                    foregroundService = mLocalBinder.getServerInstance()
                }
            }
        
            val startIntent = Intent(this, ForegroundService::class.java)
            bindService(startIntent, mConnection as ServiceConnection, Context.BIND_AUTO_CREATE);
        }
        
        
        private fun startMyService() {
            foregroundService!!.startService(this, "sdds")
        
        }
        
          private fun stopMyService() {
            if (mBounded) {
                mConnection?.let { unbindService(it) };
                mBounded = false;
            }
            val stopIntent = Intent(this, ForegroundService::class.java)
            stopService(stopIntent)
        }
        

        ForegroundService.kt

        class ForegroundService : Service() {
        
        private val CHANNEL_ID = "ForegroundService Kotlin"
        
        var mBinder: IBinder = LocalBinder()
        
        fun startService(context: Context, message: String) {
            val startIntent = Intent(context, ForegroundService::class.java)
            startIntent.putExtra("inputExtra", message)
            ContextCompat.startForegroundService(context, startIntent)
        }
        
        fun stopService(context: Context) {
            val stopIntent = Intent(context, ForegroundService::class.java)
            context.stopService(stopIntent)
        }
        
        override fun onBind(intent: Intent?): IBinder? {
            return mBinder
        }
        
        
        class LocalBinder : Binder() {
            fun getServerInstance(): ForegroundService? {
                return ForegroundService()
            }
        }}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多