gpt4 book ai didi

android - 为什么我们不能直接调用android(基于AIDL)远程服务的api?

转载 作者:搜寻专家 更新时间:2023-11-01 07:39:44 24 4
gpt4 key购买 nike


我正在编写一个简单的基于 AIDL 的 android 远程服务和一个客户端来访问远程服务公开的 API。我在互联网上查了一下,在每个帖子中,人们都在客户端代码的按钮的 onClickListener() 方法中调用了远程服务 API。但是,当我尝试在 onClickListener() 方法之外调用远程服务公开的 API 时,它会抛出 NullPointerException,表明我的服务对象尚未初始化(请检查客户端代码的 onCreate 方法中的注释)。我已将我的代码附在这个问题上。如果有人能向我解释为什么会这样,那就太好了。
这是客户端代码:

package com.myapp.myclient;

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.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.myapp.myservice.RemoteServiceInterface;

public class MyClient extends Activity {

RemoteServiceInterface remoteInterface;
ServiceConnection connection;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Intent i = new Intent();
i.setAction("com.myapp.myservice.RemoteService");

startRemoteInterface(i);
bindRemoteInterface(i);

/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}

/* Whereas this code does work. */
Button getMessage = (Button)findViewById(R.id.getMessage);
getMessage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
String msg = null;
try {
msg = remoteInterface.getMessage();
} catch (RemoteException e) {
e.printStackTrace();
}

Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}

class RemoteServiceConnection implements ServiceConnection{

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
remoteInterface = RemoteServiceInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {
}
}

private void startRemoteInterface(Intent i) {
startService(i);
}

private void bindRemoteInterface(Intent i) {
if(connection == null){
connection = new RemoteServiceConnection();
bindService(i, connection, Context.BIND_AUTO_CREATE);
} else {
Toast.makeText(getBaseContext(), "Service cannot bind - already bound.", Toast.LENGTH_SHORT).show();
}
}
}

这是我的远程服务代码:

package com.myapp.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class RemoteService extends Service {

@Override
public void onCreate() {
super.onCreate();
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

@Override
public void onDestroy() {
super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}

@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}

private final RemoteServiceInterface.Stub mBinder = new RemoteServiceInterface.Stub() {

@Override
public String getMessage() throws RemoteException {
return "Hello World!";
}
};
}

这是我的 aidl 文件:

package com.myapp.myservice; 

interface RemoteServiceInterface {
String getMessage();
}

提前致谢,
鲁佩什

最佳答案

bindRemoteInterface(i);

/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}

请记住,绑定(bind)是一个异步调用,您必须等待 onServiceConnected 的 ServiceConnection 中的回调。并在之后执行操作。

此外,您还必须使用 asInterface 方法来获取连接的真实接口(interface),google aidl example 演示了这一点。

    RemoteServiceInterface mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Following the example above for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service
mIRemoteService = RemoteServiceInterface.Stub.asInterface(service);
}

// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
mIRemoteService = null;
}
};

然后您可以调用 mIRemoteService 对象。直接在 onServiceConnected 回调中或通过通知服务。

关于android - 为什么我们不能直接调用android(基于AIDL)远程服务的api?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5675417/

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