简体   繁体   English

AIDL 客户端未绑定到远程服务

[英]AIDL Client does not bind to remote service

I am trying to run a simple multiplication with a remote service.我正在尝试使用远程服务运行简单的乘法。 I have AIDL server file declaring and defining methods.我有 AIDL 服务器文件声明和定义方法。 In AIDL, i have copied the same AIDL file as server under the server's package name.在 AIDL 中,我在服务器的 package 名称下复制了与服务器相同的 AIDL 文件。 I have given the action for the intent filter of server's service.我已经给出了服务器服务的意图过滤器的操作。 Still my AIDL client code is not connecting to the service.我的 AIDL 客户端代码仍然没有连接到服务。

AIDLServer: AIDL服务器:

Manifest显现

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

ICalService.aidl ICalService.aidl

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

CalService.java 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;
    }
}

AIDLCLient: AIDLC客户端:

MainActivity.java 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();
        }
    };

The code shows its an implicit intent used while bindService call.该代码显示了其在 bindService 调用时使用的隐式意图。

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

If you are above API level 21, you must update your code with an explicit intent.如果您的 API 级别高于 21,则必须以明确的意图更新您的代码。 Please update your code with setClassName() API to make the bind service call with an explicit intent.请使用 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");
    }

Please note the following:请注意以下事项:

Caution: To ensure that your app is secure, always use an explicit intent when starting a Service and don't declare intent filters for your services.注意:为确保您的应用程序安全,请在启动服务时始终使用显式意图,并且不要为您的服务声明意图过滤器。 Using an implicit intent to start a service is a security hazard because you cannot be certain of the service that responds to the intent, and the user cannot see which service starts.使用隐式意图启动服务是一种安全隐患,因为您无法确定响应意图的服务,并且用户无法看到启动了哪个服务。 Beginning with Android 5.0 (API level 21), the system throws an exception if you call bindService() with an implicit intent.从 Android 5.0(API 级别 21)开始,如果您使用隐式意图调用 bindService(),系统将抛出异常。 Ref: https://developer.android.com/guide/components/services参考: https : //developer.android.com/guide/components/services

Also check this too,也检查这个,

"To receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter" “要接收隐式意图,您必须在意图过滤器中包含 CATEGORY_DEFAULT 类别”

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

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

All you need is to add in client app Manifest, where you want tu bind 3rd party app Service.您只需要在客户端应用程序清单中添加您想要绑定 3rd 方应用程序服务的位置。 With the same package name you set in the Intent:使用您在 Intent 中设置的相同 package 名称:

val intent = Intent("example_action")
intent.`package` = "your package name"
bindService(intent, connection, Context.BIND_AUTO_CREATE)

Manifest:显现:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="io.github.asvid.services.client">
    <queries>
         <package android:name="io.github.asvid.services.server" />
    </queries>
...
</manifest>

Alternatively you can stay with compileSdk 29 but I don't recommend that:)或者,您可以继续使用 compileSdk 29,但我不建议这样做:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM