Android 如何从活动中调用服务的方法?

Android 如何从活动中调用服务的方法?,android,service,android-activity,Android,Service,Android Activity,我只想从我的活动中调用本地服务的方法。我该怎么做呢?我不知道你的问题出在哪里,请发一些代码。 使用活页夹,活动可以访问服务对象。有关在活动和服务之间创建连接的信息,请参见API中的示例 在活动中包含服务对象后,您只需调用: mService.yourMethod() 如果您能准确地描述您的问题,并且如我所说,发布一些代码片段,我们可以为您提供更好的帮助 一种方法是定义一个接口,并使用活页夹子系统执行IPC。在我发布的链接上有一系列很好的说明。如果你有问题,我会从那里开始,然后在这里发帖。尽管是一

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

我不知道你的问题出在哪里,请发一些代码。 使用活页夹,活动可以访问服务对象。有关在活动和服务之间创建连接的信息,请参见API中的示例

在活动中包含服务对象后,您只需调用:
mService.yourMethod()

如果您能准确地描述您的问题,并且如我所说,发布一些代码片段,我们可以为您提供更好的帮助

一种方法是定义一个接口,并使用
活页夹
子系统执行IPC。在我发布的链接上有一系列很好的说明。如果你有问题,我会从那里开始,然后在这里发帖。尽管是一个相当复杂的主题(IPC),Android和
活页夹在让它变得非常简单方面做得非常好(至少从一开始,我相信如果你愿意,你可以让它变得复杂;-)


编辑正如注释中指出的那样,如果
服务
和客户端在同一进程中运行,则不需要进行编辑。除非另行指定,否则这是默认设置。但是,不管怎样,它仍然可以工作,只是增加了一点复杂性。

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


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

下面是一个可能有帮助的例子
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;
        }
    };
}
如何调用普通Java方法? 服务是一个Java类。那么,您将如何调用服务方法呢

serviceObj.method();
现在真正的问题是如何创建服务对象?
Service serviceObj=new Service()

绝对不是。

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

这就是如何从中获取服务对象

一旦掌握了serviceObject。它将像任何普通Java对象一样工作。
图中解释的上述内容称为绑定服务

绑定使从活动中观察后台服务成为可能。通过绑定,我们可以通过两种方式进行通信,即活动服务
Prateek Yadav已经提供了一个优秀的代码片段。你可以用这个

没什么要记住的
  • 永远不要忘记解除服务绑定,否则将导致资源泄漏
  • 您可以按任意顺序调用
    startService(intent)
    bindService(minent、mConnection、BIND\u AUTO\u CREATE)
    。绑定和启动服务是两件独立的事情

    • 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)
      }
      
      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()
          }
      }}
      
      ForegroundService.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)
      }
      
      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()
          }
      }}
      

      你为什么不放一些有用资源的链接呢?发布一些关于如何绑定服务并随后调用其方法的框架片段:)@Juri不知从哪里冒出来,它是LinkedL,只有当服务和活动在不同的应用程序中时才需要它。如果您的服务和活动是应用程序本地的(这是常见的情况),请参阅response by@hackbod@odedfos你部分是对的。使用AIDL的必要性取决于调用方和被调用方是否处于不同的进程中,而不一定是不同的应用程序。大多数情况下,应用程序只有一个进程,因此这不是问题,但您可以指定服务在与UI不同的进程中运行,即使在同一个应用程序中也是如此。根据定义,本地服务不使用IPC,问题是关于本地服务,因此,这个答案是错误的。@Ixx默认情况下不会,但您可以指定它们在单独的进程中运行。而且,如果您在与客户机相同的进程中运行服务,这也会起作用。如果服务被强制停止,我会被呼叫到onServiceDisconnected吗?为什么呼叫一个简单的fuction@Mr.Z也许您没有将服务绑定到Android中的活动,这应该是正确的答案。谢谢你节省了我的时间。