gpt4 book ai didi

android - 如何将Activity绑定(bind)到Service,并从Activity中控制和管理Service

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:02 29 4
gpt4 key购买 nike

我正在尝试将 Activity 绑定(bind)到 LocalService 以与之交互。但是在我的 Activity 中,我只能调用 LocalBinder 中定义的方法,而不能调用 LocalService 中定义的方法。我做错了什么?

不是从头开始我读了另一个 question我已经阅读了一些如何code some sample code我的代码类似于该示例代码。我也一直在阅读一些 Service Documentation为方便起见,这里引用了文档该部分的一小段内容:

“当应用程序组件通过调用 bindService() 绑定(bind)到服务时,服务被“绑定(bind)”。绑定(bind)服务提供客户端-服务器接口(interface),允许组件与服务交互、发送请求、获取结果,,甚至通过进程间通信 (IPC) 跨进程执行此操作。绑定(bind)服务仅在另一个应用程序组件绑定(bind)到它时运行。多个组件可以同时绑定(bind)到该服务,但是当它们全部解除绑定(bind)时,服务就会被破坏。”

可是我做不到。如上所述,我能做的最好的事情就是在我的 LocalBinder 中定义我的 Activity 调用方法。我没有取得像上面黑色突出显示的部分那​​样的成就。

如果有帮助,这里是我的代码的相关部分。

要绑定(bind)的 LocalService:

/**************************************************************************************************
* Filename: LocalService.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains the LocalService (extends Service) for our Local Service app
**************************************************************************************************/

package com.marie.localservicesample;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class LocalService extends Service {
private NotificationManager mNM;

// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
private int NOTIFICATION = R.string.local_service_started;

// just some arbitrary numbers for test purposes
public static int statusCode = 99;
public static int emptyMsg = 549;

// I get my Extras from onStartCommand and use in ServiceWorker() thread
public static final String EXTRA_MAC = "com.marie.localservicesample.EXTRA_MAC";
private String macString;

public static final String EXTRA_MESSENGER = "com.marie.localservicesample.EXTRA_MESSENGER";
private Messenger messenger;

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//private static final String macString = "00:06:66:02:D0:EC";

Boolean stop_receive_data = false;

// This is the object that receives interactions from clients. See
// RemoteService for a more complete example - or not because
// this is a local service
private final IBinder mBinder = new LocalBinder();

@Override
public IBinder onBind(Intent intent) {
Log.i("onBind", "called in LocalService" );
Log.i("onBind", "intent: " + intent.toString());
Log.i("onBind", "mBinder: " + mBinder);
return mBinder;
}

@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

// Display a notification about us starting. We put an icon in the status bar.
showNotification();
}

// Call this at the end of onStartCommand() after we got the Extras
public void afterStartCommand() {
Thread thr = new Thread(null, new ServiceWorker(), "LocalService");
thr.start();
}

/*
* This is the ServiceWorker thread that passes messages to the handler defined in
* the Controller activity.
*/
class ServiceWorker implements Runnable
{
public void run() {
// do background processing here... something simple
Looper.prepare();

BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice btDevice = btAdapter.getRemoteDevice(macString);
BluetoothSocket btSocket = null;
InputStream btIstream = null;
OutputStream btOstream = null;
try {
btSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
btSocket.connect();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
btIstream = btSocket.getInputStream();
btOstream = btSocket.getOutputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
int data = btIstream.read();

// reset the bluetooth device
while (data != 63) {
Log.d("LocalService", "resetting bluetooth device");
btOstream.write('r');
data = btIstream.read();
}

StringBuffer strBuffer = new StringBuffer("");
Boolean dataBegin = false;

int ndxPlus = 0;

while (data != -1) {
char printableB = (char) data;
if (data < 32 || data > 126) {
//printableB = ' ';
}
//Log.d("LocalService", Character.toString(printableB) + "(" + data + ")");

if (data == 63) {
btOstream.write('$');
btOstream.write(',');
}
if (data == 45) {
btOstream.write('1');
btOstream.write(',');
dataBegin = true;
}
if (dataBegin == true) {
strBuffer = strBuffer.append(Character.toString(printableB));
}
if (data == 13) {
dataBegin = false;
//Log.d("LocalServiceDataString", strBuffer.toString());

// send data to the handler to plot the data
Message msg = Message.obtain();
msg.what = Controller.MESSAGE_MAC;
msg.obj = strBuffer;
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}

strBuffer = new StringBuffer("");
if (ndxPlus < 0) {
btOstream.write('+');
ndxPlus++;
}
}

data = btIstream.read();
if (stop_receive_data) data = -1;

}

} catch (IOException e1) {
e1.printStackTrace();
}
try {
btSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}

LocalService.this.stopSelf();
Looper.loop();
// stop the service when done...
// Or use the unbindBtn in the MainActivity class?
}
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);

Bundle extras = intent.getExtras();

messenger = (Messenger)extras.get(EXTRA_MESSENGER);
macString = extras.getString(EXTRA_MAC);

afterStartCommand();

// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}

@Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(NOTIFICATION);
stop_receive_data = true;
// Tell the user we stopped.
Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
}

/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.local_service_started);

// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.stat_sample, text, System.currentTimeMillis());

// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Controller.class), 0);

// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.local_service_label), text, contentIntent);

// Send the notification.
mNM.notify(NOTIFICATION, notification);
}
}

绑定(bind)到本地服务的 Activity :

/**************************************************************************************************
* Filename: Binding.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains the Binding class for our Local Service application
**************************************************************************************************/
package com.marie.localservicesample;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

/*
* Example of binding and unbinding to the local service.
* This demonstrates the implementation of a service which the client will
* bind to, receiving an object through which it can communicate with the service.
*/

public class Binding extends Activity {
private ILocalBinder mBoundService;
private boolean mIsBound;

private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = (ILocalBinder)service;

int statusCode = mBoundService.getStatusCode();

Log.d("Binding.java","called onServiceConnected. statusCode: " + statusCode);

Toast.makeText(Binding.this, R.string.local_service_connected,
Toast.LENGTH_SHORT).show();
}

public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;

Log.d("Binding", "called onServiceDisconnected");

Toast.makeText(Binding.this, R.string.local_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};

void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(Binding.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}

void doUnbindService() {
if (mIsBound) {
int statusCode = mBoundService.getStatusCode();
if (statusCode != 0) Log.d("doUnbindService", "Binding.java statusCode: " + statusCode);

// Tell the user we did an unbind
Toast.makeText(this, R.string.local_service_unbound, Toast.LENGTH_SHORT).show();

// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.local_service_binding);

// Watch for button clicks.
Button button = (Button)findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button)findViewById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
}

private OnClickListener mBindListener = new OnClickListener() {
public void onClick(View v) {
doBindService();
}
};

private OnClickListener mUnbindListener = new OnClickListener() {
public void onClick(View v) {
doUnbindService();
}
};

@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
}

我的 ILocalBinder 和 LocalBinder:

/**************************************************************************************************
* Filename: ILocalBinder.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains an example interface for my LocalBinder
**************************************************************************************************/

package com.marie.localservicesample;

public interface ILocalBinder {

public int getStatusCode();
}

/**************************************************************************************************
* Filename: LocalBinder.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains the LocalBinder class for our Local Service application
**************************************************************************************************/

package com.marie.localservicesample;

import android.os.Binder;

import com.marie.localservicesample.LocalService;

/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder implements ILocalBinder {
@Override
public int getStatusCode() {
return LocalService.statusCode;
}

}

谢谢!

最佳答案

参见 local service example .

只需将他们拥有的 Binder 类代码复制到您的服务中,而不是为其创建一个单独的文件:(在 LocalService 类声明中)

public class LocalService {
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();

/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}

...
}

然后:

public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder)service).getService();

现在您可以使用 mBoundService 直接访问您的服务。

关于android - 如何将Activity绑定(bind)到Service,并从Activity中控制和管理Service,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6723026/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com