无法连接到Android 5.1本地原生套接字。

3
我是一名有用的助手,可以为您翻译文本。
我有一个命令行工具,它发送广播并等待结果。
服务器代码(省略错误处理):
    int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
    {
        int nameLen = strlen(name);
        pAddr->sun_path[0] = '\0';
        strcpy(pAddr->sun_path+1, name);
        pAddr->sun_family = AF_LOCAL;
        *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
        return 0;
    }

    int main(int argc, char* argv[])
    {
        //...

        // Create socket in abstract namespace
        struct sockaddr_un sockAddr = {0};
        socklen_t sockLen;
        makeAddr("SOCKET_NAME", &sockAddr, &sockLen);

        int serverFd = socket(AF_LOCAL, SOCK_STREAM, PF_UNIX));

        bind(serverFd, (const struct sockaddr*) &sockAddr, sockLen);

        listen(serverFd, 5);

        //set socket non-blocking
        int flags = fcntl(serverFd, F_GETFL, 0);
        fcntl(serverFd, F_SETFL, flags | O_NONBLOCK);

        pollfd pollFd = {0};
        pollFd.fd = serverFd;
        pollFd.events = POLLIN | POLLRDHUP;

        // Send brodcast 
        system("am broadcast ...");

        for(;;)
        {
            // Wait result 
            int pollResult = poll(&pollFd, 1, timeout);
        // Process result

Java客户端代码:

public class CommandReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {

            LocalSocket socket = new LocalSocket();
            LocalSocketAddress address = new LocalSocketAddress("SOCKET_NAME", LocalSocketAddress.Namespace.ABSTRACT);
            socket.connect(address);

            // Do something and send result asynchronously 

它在 Android 5.1 之前的版本上运行正常。在 Android 5.1 上,connect() 抛出异常:
java.io.IOException: Permission denied at android.net.LocalSocketImpl.connectLocal(Native Method) at android.net.LocalSocketImpl.connect(LocalSocketImpl.java:290) at android.net.LocalSocket.connect(LocalSocket.java:130)
日志中显示错误:
07-27 09:56:08.179: W: type=1400 audit(0.0:3675): avc: denied { connectto } for path=00636F6D2E6B6173706572736B792E6B617368656C6C2E534F434B45542D36313838363731373231343337393833373637 scontext=u:r:untrusted_app:s0 tcontext=u:r:shell:s0 tclass=unix_stream_socket permissive=0
我找到了相关的 Android 修复程序: https://android.googlesource.com/device/moto/shamu/+/b2db40f

所以,自Android 5.1以来它将不再起作用? 我该怎么办(也许可以通过某种方式设置权限)? 或者是否有另一种机制可以从本地命令行工具发送数据并等待结果?

2个回答

1

使用管道而不是套接字: 使用poll()函数在命名管道上进行O_RDWR操作

在Java进程中创建管道:

        mkfifo(cpath, 0);
        chmod(cpath, S_IRWXU|S_IROTH|S_IRGRP);

在本地进程中打开管道:

int serverFd = open(PIPE_NAME, O_RDONLY | O_NONBLOCK);
pollfd pollFd = {0};
pollFd.fd = serverFd.get();
pollFd.events = POLLIN | POLLRDHUP;

// send command
....

for(;;)
{
    int pollResult = poll(&pollFd, 1, timeout);

0
在我的安卓10经验中,抽象命名空间Unix域套接字和未命名管道可以在同一应用程序内部使用,但不能跨不同应用程序使用。我两者都以natively的方式实现了客户端和服务器。
对于命名管道,您必须在您拥有写权限的地方创建文件。基本上是您的应用程序数据文件夹。
对于进程间通信,您可以尝试从一个进程发送文件描述符到另一个进程以根据this授予访问权限,但我不确定它如何工作。我最终使用网络套接字来完成这个任务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接