Android 多进程开发 - FileDescriptor、Uri、AIDL 接口定义不能抛出异常

FileDescriptor

1、AIDL
  • IMyAidlInterface.aidl,这里是位于 src/main/java/com/my/common 包下
java 复制代码
package com.my.common;

import android.os.ParcelFileDescriptor;

interface IMyAidlInterface {
    ParcelFileDescriptor getFileDescriptor();
    void setFileDescriptor(in ParcelFileDescriptor parcelFileDescriptor);
}
2、Server
java 复制代码
private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {

    @Override
    public ParcelFileDescriptor getFileDescriptor() throws RemoteException {
        File filesDir = getFilesDir();
        File file = new File(filesDir, "shared_file.dat");

        // 如果示例文件不存在,则创建,并写入一些数据
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write("server content".getBytes());
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void setFileDescriptor(ParcelFileDescriptor parcelFileDescriptor) throws RemoteException {
        if (parcelFileDescriptor != null) {
            try (FileInputStream fileInputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
                byte[] content = new byte[fileInputStream.available()];
                int read = fileInputStream.read(content);
                Log.i(TAG, "read " + read + " bytes from file");
                Log.i(TAG, "file content: " + new String(content));
            } catch (IOException e) {
                Log.i(TAG, "open file error: " + e.getMessage());
            } finally {
                try {
                    parcelFileDescriptor.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
};
3、Client
  1. 调用 getFileDescriptor 方法
java 复制代码
try {
    ParcelFileDescriptor parcelFileDescriptor = myAidlInterface.getFileDescriptor();
    Log.i(TAG, "getFileDescriptor method success");

    if (parcelFileDescriptor != null) {
        try (FileInputStream fileInputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
            byte[] content = new byte[fileInputStream.available()];
            int read = fileInputStream.read(content);
            Log.i(TAG, "read " + read + " bytes from file");
            Log.i(TAG, "file content: " + new String(content));
        } catch (IOException e) {
            Log.i(TAG, "open file error: " + e.getMessage());
        } finally {
            try {
                parcelFileDescriptor.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
} catch (RemoteException e) {
    e.printStackTrace();
    Log.e(TAG, "getFileDescriptor method error: " + e.getMessage());
}
  1. 调用 setFileDescriptor 方法
java 复制代码
File filesDir = getFilesDir();
File file = new File(filesDir, "shared_file.dat");

// 如果示例文件不存在,则创建,并写入一些数据
if (!file.exists()) {
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write("client content".getBytes());
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

try {
    ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    try {
        myAidlInterface.setFileDescriptor(parcelFileDescriptor);
        Log.i(TAG, "setFileDescriptor method success");
    } catch (RemoteException e) {
        e.printStackTrace();
        Log.e(TAG, "setFileDescriptor method error: " + e.getMessage());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
4、Test
  1. 调用 getFileDescriptor 方法,输出结果如下

    getFileDescriptor method success
    read 14 bytes from file
    file content: server content

  2. 调用 setFileDescriptor 方法,输出结果如下

    read 14 bytes from file
    file content: client content
    setFileDescriptor method success


Uri

1、AIDL
  • IMyAidlInterface.aidl,这里是位于 src/main/java/com/my/common 包下
java 复制代码
package com.my.common;

import android.net.Uri;

interface IMyAidlInterface {
    Uri getUri();
    void setUri(in Uri uri);
}
2、Server
java 复制代码
private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {

    @Override
    public Uri getUri() throws RemoteException {
        File filesDir = getFilesDir();
        File file = new File(filesDir, "shared_file.dat");

        // 如果示例文件不存在,则创建,并写入一些数据
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write("server content".getBytes());
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        Uri uri = FileProvider.getUriForFile(ServerService.this, getApplicationContext().getPackageName() + ".fileprovider", file);

        // 授予临时权限
        // 第一个参数是客户端应用包名
        grantUriPermission("com.my.client", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

        return uri;
    }

    @Override
    public void setUri(Uri uri) throws RemoteException {
        if (uri != null) {
            try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
                byte[] content = new byte[inputStream.available()];
                int read = inputStream.read(content);
                Log.i(TAG, "read " + read + " bytes from uri");
                Log.i(TAG, "uri content: " + new String(content));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
};
3、Client
  1. 调用 getUri 方法
java 复制代码
try {
    Uri uri = myAidlInterface.getUri();
    Log.i(TAG, "getUri method success");

    if (uri != null) {
        try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
            byte[] content = new byte[inputStream.available()];
            int read = inputStream.read(content);
            Log.i(TAG, "read " + read + " bytes from uri");
            Log.i(TAG, "uri content: " + new String(content));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
} catch (RemoteException e) {
    e.printStackTrace();
    Log.e(TAG, "getUri method error: " + e.getMessage());
}
  1. 调用 setUri 方法
java 复制代码
File filesDir = getFilesDir();
File file = new File(filesDir, "shared_file.dat");

// 如果示例文件不存在,则创建,并写入一些数据
if (!file.exists()) {
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write("client content".getBytes());
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", file);
grantUriPermission("com.my.server", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
    myAidlInterface.setUri(uri);
    Log.i(TAG, "setUri method success");
} catch (RemoteException e) {
    e.printStackTrace();
    Log.e(TAG, "setUri method error: " + e.getMessage());
}
4、Test
  1. 调用 getUri 方法,输出结果如下

    getUri method success
    read 14 bytes from uri
    uri content: server content

  2. 调用 setUri 方法,输出结果如下

    read 14 bytes from uri
    uri content: client content
    setUri method success


AIDL 接口定义不能抛出异常

  • 在 AIDL 接口定义中,方法签名本身不能包含 throws 关键字来声明抛出异常,会导致编译错误
java 复制代码
int add(int a, int b) throws RemoteException;
复制代码
# 输出结果

syntax error, unexpected identifier, expecting '=' or ';'
java 复制代码
oneway void doSomething() throws RemoteException;
复制代码
# 输出结果

syntax error, unexpected identifier, expecting '=' or ';'
  • 将光标移动到 throws 关键字上,会出现如下提示信息

    AidlTokenTypes. ASSIGN expected, got 'throws'

相关推荐
宸津-代码粉碎机6 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
噢,我明白了7 小时前
java中唯一键和幂等键的应用
java·后端
程序猿乐锅7 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
考虑考虑7 小时前
synchronized字符串常量
java·后端·java ee
长谷深风1117 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
m0_587383007 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
Escalating_xu7 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言
蒸鱼Yuzheng7 小时前
设备端性能工件可靠导出:断点续传、哈希、manifest 与失败恢复
android·自动化测试·python·adb·数据完整性
周杰偷奶茶8 小时前
【Java】数据类型与变量
java·开发语言
code斗8 小时前
Java数据结构:堆详解
java·开发语言·数据结构