首页 > 解决方案 > AIDL 客户端未绑定到远程服务

问题描述

我正在尝试使用远程服务运行简单的乘法。我有 AIDL 服务器文件声明和定义方法。在 AIDL 中,我在服务器的包名称下复制了与服务器相同的 AIDL 文件。我已经给出了服务器服务的意图过滤器的操作。我的 AIDL 客户端代码仍然没有连接到服务。

AIDL服务器:

显现

<service
            android:name=".CalService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <action android:name="mutliply"/>
            </intent-filter>
        </service>

ICalService.aidl

interface ICalService {
        String getMessage(String name);
        int getResult(int val1, int val2);
}

CalService.java

public class CalService extends Service {
    public CalService() {
    }

    private final ICalService.Stub binder = new ICalService.Stub() {
        @Override
        public String getMessage(String name) throws RemoteException {
            return "Hello " + name + ". The result is: ";
        }

        @Override
        public int getResult(int val1, int val2) throws RemoteException {
            return val1 * val2;
        }
    };

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

AIDLC客户端:

MainActivity.java

@Override
    protected void onStart() {
        super.onStart();
        editName = (EditText) findViewById(R.id.editName);
        editVal1 = (EditText) findViewById(R.id.editVal1);
        editVal2 = (EditText) findViewById(R.id.editVal2);
        resultView = (TextView) findViewById(R.id.resultView);

        if(calService == null) {
            Log.v("CALSERVICE", "cal service null");
            Intent it = new Intent("multiply");
            it.setPackage("com.example.aidlserver");
            if(getBaseContext().getApplicationContext().bindService(
                    it, connection, Context.BIND_AUTO_CREATE
            ) == true){
                Log.v("Bind", "Bind service Succeeded");
            } else {
                Log.v("Bind", "Bind service failed");
            }
        } else {
            Log.v("Cal", "Cal Service not null");
        }
    }

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

    public void mutiply(View v) {
        switch (v.getId()) {
            case R.id.btnCal:
                int num1 = Integer.parseInt(editVal1.getText().toString());
                int num2 = Integer.parseInt(editVal2.getText().toString());
                try {
                    int result = calService.getResult(num1, num2);
                    String msg = calService.getMessage(editName.getText().toString());
                    resultView.setText(msg + result);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }


    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("onServiceConnected", "Connected");
            calService = ICalService.Stub.asInterface(service);
            Toast.makeText(getApplicationContext(), "Service Connected",
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("onServiceDisconnected", "Disconnected");
            calService = null;
            Toast.makeText(getApplicationContext(), "Service Disconnected",
                    Toast.LENGTH_SHORT).show();
        }
    };

标签: javaandroidaidl

解决方案


该代码显示了它在调用 bindService 时使用的隐式意图。

Intent it = new Intent("multiply");
it.setPackage("com.example.aidlserver");

如果您的 API 级别高于 21,则必须以明确的意图更新您的代码。请使用 setClassName() API 更新您的代码,以便以明确的意图进行绑定服务调用。

    Intent it = new Intent("multiply");            
    it.setClassName("com.example.aidlserver","com.example.aidlserver.CalService");
    if(getBaseContext().getApplicationContext().bindService(it, connection, Context.BIND_AUTO_CREATE) == true){
        Log.v("Bind", "Bind service Succeeded");
    } else {
        Log.v("Bind", "Bind service failed");
    }

请注意以下事项:

注意:为确保您的应用程序安全,请始终在启动服务时使用显式意图,并且不要为您的服务声明意图过滤器。使用隐式意图启动服务是一种安全隐患,因为您无法确定响应该意图的服务,并且用户无法看到哪个服务启动。从 Android 5.0(API 级别 21)开始,如果您使用隐式 Intent 调用 bindService(),系统将引发异常。参考:https ://developer.android.com/guide/components/services

也检查一下,

“要接收隐式意图,您必须在意图过滤器中包含 CATEGORY_DEFAULT 类别”

<category android:name="android.intent.category.DEFAULT"/>

https://developer.android.com/guide/components/intents-filters#Receiving


推荐阅读