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

时间:2011-01-30 19:21:39

标签: android service android-activity

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

6 个答案:

答案 0 :(得分:56)

这是一个可能有用的例子 的 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;
        }
    };
}

答案 1 :(得分:28)

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

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

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

答案 2 :(得分:2)

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

编辑正如评论中所指出的,如果Service和客户端在同一进程中运行,则不需要这样做。除非您另行指定,否则这是默认值。但是,它仍然有效,它只会增加一点复杂性。

答案 3 :(得分:1)

如何调用普通的Java类方法?

const html = document.querySelector("#html-area");
const md = document.querySelector("#markdown-area");

const bold = word =>
  `<span class="bold">${word.substring(1, word.length - 1)}</span>`;

const boldOrNot = word =>
  word.startsWith("*") && word.endsWith("*") && word.length > 2
    ? bold(word)
    : word;

html.addEventListener("keyup", function(e) {
  const input = e.target.value;
  const output = input.split(" ").map(boldOrNot).join(" ");
  md.innerHTML = output;
});

服务是Java类。那么您将如何调用服务方法?

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

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

serviceObj.method(); 绝对不是。
在Android中,服务是由Android OS创建,销毁和管理的系统组件。
为了创建服务对象,我们需要`IBinder。

  

这是从IBinder获取服务对象的流程。

enter image description here

一旦您拥有一个serviceObject。它将像任何普通的Java对象一样工作。 在Android中,我们需要遵循某些 PATTERN 才能使上述流程成为可能。这种模式称为绑定服务
绑定使观察活动中的后台服务成为可能。通过绑定,我们可以通过两种方式进行通信,即Activity <---> Service。 Prateek Yadav已经提供了出色的代码段。您可以使用它。

要记住的几件事

  • 请不要忘记取消绑定服务,否则将导致ResourceLeak。
  • 您可以按任意顺序呼叫Service serviceObj = new Service();startService(intent)。绑定和启动服务是两件独立的事情。

答案 4 :(得分:0)

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

在您的活动中拥有服务对象,您只需致电:
                       mService.yourMethod();
如果您准确描述您的问题,我们可以帮助您更好,正如我所说,发布一些片段。

答案 5 :(得分:0)

科特林的等效代码

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()
    }
}}